代码改变世界

C语言 栈 链式结构 实现

2013-10-30 11:30  wid  阅读(3010)  评论(1编辑  收藏  举报

一个C语言链式结构实现的栈 mStack (GCC编译)。

  1 /**
  2 * @brief C语言实现的链式结构类型的栈
  3 * @author wid
  4 * @date 2013-10-30
  5 *
  6 * @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
  7 */
  8 
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 
 12 #define TRUE 1
 13 #define FALSE 0
 14 
 15 typedef struct SNODE
 16 {
 17     void *pelm;             //元素指针
 18     struct SNODE *next;     //指向下一栈节点
 19 }StackNode;
 20 
 21 typedef struct
 22 {
 23     StackNode *btm;      //栈底指针
 24     StackNode *top;      //指向栈顶元素
 25     int height;          //栈高度
 26 }mStack;
 27 
 28 //栈方法声明
 29 
 30 mStack *CreateStack();     //创建一个空的栈
 31 void DestroyStack( mStack *pStack );        //销毁栈
 32 void ClearStack( mStack *pStack );          //清空栈内元素
 33 int GetHeight( mStack *pStack );            //获取栈高度
 34 int IsEmpty( mStack *pStack );              //检测是否为空栈
 35 int Push( mStack *pStack, void *pdata );    //向栈内压入元素
 36 int Pop( mStack *pStack, void **pdata );    //将栈顶元素出栈
 37 int GetTop( mStack *pStack, void **pdata ); //获取栈顶元素
 38 void ForEachStack( mStack *pStack, void (*func)(void *pdata) );      //从栈顶到栈底的每个元素依次执行 func 函数
 39 
 40 
 41 //栈方法实现
 42 
 43 /**
 44 * @brief 创建一个高度为 nHeight 的栈
 45 *
 46 * @return 返回指向新建的栈的指针
 47 */
 48 mStack *CreateStack()
 49 {
 50     ///创建一个栈
 51     mStack *pStack = (mStack *)malloc( sizeof(mStack) );
 52 
 53     ///令栈顶指向栈底指向NULL
 54     pStack->top = pStack->btm = NULL;
 55 
 56     ///初始栈高度为0
 57     pStack->height = 0;
 58 }
 59 
 60 /**
 61 * @brief 销毁栈 pStack
 62 *
 63 * @param pStack 指向待销毁的栈的指针
 64 *
 65 * @return void
 66 */
 67 void DestroyStack( mStack *pStack )
 68 {
 69     StackNode *tmp = NULL;
 70 
 71     ///释放栈内节点
 72     while( tmp != NULL )
 73     {
 74         tmp = pStack->top->next;
 75         free( pStack->top );
 76         pStack->top = tmp;
 77     }
 78 
 79     ///释放栈
 80     free( pStack );
 81 }
 82 
 83 /**
 84 * @brief 清空栈内元素
 85 *
 86 * @param pStack 指向待清空元素的栈的指针
 87 *
 88 * @return void
 89 */
 90 void ClearStack( mStack *pStack )
 91 {
 92     StackNode *tmp = NULL;
 93     while( tmp != NULL )
 94     {
 95         tmp = pStack->top->next;
 96         free( pStack->top );
 97         pStack->top = tmp;
 98     }
 99 
100     pStack->top = pStack->btm = NULL;
101 
102     pStack->height = 0;
103 }
104 
105 /**
106 * @brief 获取栈当前高度
107 *
108 * @param 指向待获取高度的栈的指针
109 *
110 * @return 返回栈当前高度
111 */
112 int GetHeight( mStack *pStack )
113 {
114     return pStack->height;
115 }
116 
117 /**
118 * @brief 检测是否为空栈
119 *
120 * @param pStack 指向待检测的栈的指针
121 *
122 * @return 若为空, 则返回 TRUE, 否则返回 FALSE
123 */
124 int IsEmpty( mStack *pStack )
125 {
126     return pStack->height == 0 ? TRUE : FALSE;
127 }
128 
129 /**
130 * @brief 向栈内压入元素
131 *
132 * @param pStack 待压入元素的栈
133 * @param pdata 指向待压入栈元素的指针
134 *
135 * @return 返回成功入栈后栈的高度
136 */
137 int Push( mStack *pStack, void *pdata )
138 {
139     ///创建一个栈节点
140     StackNode *pNode = (StackNode *)malloc( sizeof(StackNode) );
141 
142     ///为该节点赋值
143     pNode->pelm = pdata;
144     pNode->next = pStack->top;
145 
146     ///令栈顶指向最新节点
147     pStack->top = pNode;
148 
149     ++pStack->height;
150 }
151 
152 /**
153 * @brief 将栈顶元素出栈
154 *
155 * @param pStack 指向待执行出栈操作的栈的指针
156 * @param pdata 接收弹出的元素的指针
157 *
158 * @return 出栈成功则返回出栈后栈的高度, 否则返回 -1
159 */
160 int Pop( mStack *pStack, void **pdata )
161 {
162     ///检测是否为空栈
163     if( pStack->top == pStack->btm  )
164         return -1;
165 
166     ///取得栈节点数据元素值
167     *pdata = pStack->top->pelm;
168 
169     ///将栈顶指针向下退一位
170     StackNode *p = pStack->top->next;
171     free( pStack->top );
172     pStack->top = p;
173 
174     return --pStack->height;
175 }
176 
177 /**
178 * @brief 获取栈顶元素到 pt
179 *
180 * @param pStack 指向待弹出元素的栈的指针
181 * @param pdata 指向接收弹出的元素的指针
182 *
183 * @return 获取成功则返回栈顶元素的位置, 否则返回 -1
184 *
185 * @note 元素位置由 0 计起
186 */
187 int GetTop( mStack *pStack, void **pdata )
188 {
189     ///检测是否为空栈
190     if( pStack->height == 0 )
191         return -1;
192 
193     *pdata = pStack->top->pelm;
194 
195     return pStack->height - 1;
196 }
197 
198 /**
199 * @brief 从栈底到栈顶的每个元素依次执行 func 函数
200 *
201 * @param pStack 指向待处理的栈的指针
202 * @param func 需要执行的函数的指针
203 *
204 * @return void
205 */
206 void ForEachStack( mStack *pStack, void (*func)(void *pt) )
207 {
208     StackNode *tmp = pStack->top;
209     while( tmp != NULL )
210     {
211         func( tmp->pelm );
212         tmp = tmp->next;
213     }
214 }
215 
216 void display( void *pn )
217 {
218     printf( "%d ", *(int *)pn );
219 }
220 
221 int main()
222 {
223     int a = 10, b = 20, c = 30, n = 0;
224     void *pa = NULL;
225 
226     ///测试 CreateStack
227     mStack *psk = CreateStack();
228 
229     ///测试 IsEmpty、GetHeight
230     if( IsEmpty(psk) == TRUE )
231         printf( "Init Height = %d\n", GetHeight(psk) );
232 
233     ///测试 Push
234     printf("压入数字 10\n"); Push( psk, &a );
235     printf("压入数字 20\n"); Push( psk, &b );
236     printf( "压入2元素后栈高度 = %d\n", GetHeight(psk) );
237 
238     ///测试 Pop
239     printf( "\n测试 Pop:\n" );
240     n = Pop( psk, &pa );
241     if( n != -1 )
242         printf( "Pop = %d\n", *(int *)pa );
243 
244     n = Pop( psk, &pa );
245     if( n != -1 )
246         printf( "Pop = %d\n", *(int *)pa );
247 
248     n = Pop( psk, &pa );
249     if( n != -1 )
250         printf( "Pop = %d\n", *(int *)pa );
251 
252     ///测试清空栈
253     Push( psk, &a );
254     printf("\n清空栈..");
255     ClearStack( psk );
256     printf( "\n清空后栈高度 = %d\n", GetHeight(psk) );
257 
258     ///测试 ForEachStack
259     printf("\n\压入3元素..");
260     Push( psk, &a );
261     Push( psk, &b );
262     Push( psk, &c );
263     printf("\n测试 ForEachStack: "); ForEachStack( psk, display );
264 
265     ///测试GetTop
266     printf("\n测试GetTop:\n");
267     n = GetTop( psk, &pa );
268     if( n != -1 )
269         printf( "GetTop = %d\n", *(int *)pa );
270 
271     ///再次输出当前栈高度
272     printf( "\n当前栈高度Height = %d\n", GetHeight(psk) );
273 
274     ///测试 DestroyStack
275     printf("\n销毁栈..\n");
276     DestroyStack( psk );
277 
278     return 0;
279 }

测试运行:

 

若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢。