代码改变世界

C语言 栈 顺序结构 实现

2013-10-29 13:26  wid  阅读(1318)  评论(0编辑  收藏  举报

一个能够自动扩容的顺序结构的栈 ArrStack 实例 (GCC编译)。

  1 /**
  2 * @brief C语言实现的顺序结构类型的栈
  3 * @author wid
  4 * @date 2013-10-29
  5 *
  6 * @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
  7 */
  8 
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 #include <string.h>
 12 
 13 #define TRUE 1
 14 #define FALSE 0
 15 
 16 typedef struct Point2D
 17 {
 18     int x;
 19     int y;
 20 }ElemType;      //栈元素结构
 21 
 22 typedef struct
 23 {
 24     ElemType *btm;      //栈底
 25     ElemType *top;      //栈顶
 26     int height;         //栈高
 27     int size;           //栈总大小
 28 }ArrStack;      //栈结构
 29 
 30 //栈方法声明
 31 ArrStack *CreateStack( int nSize );             ///创建一个大小为nSize的栈
 32 void DestroyStack( ArrStack *pStack );          ///销毁栈 pStack
 33 void ClearStack( ArrStack *pStack );            ///清空栈 pStack 内的元素
 34 int GetHeight( ArrStack *pStack );              ///获取栈 pStack 的高度
 35 int GetSize( ArrStack *pStack );                ///获取栈 pStack 的总容量
 36 int IsEmpty( ArrStack *pStack );                ///检测栈 pStack 是否为空栈
 37 int Push( ArrStack *pStack, ElemType *pt );     ///将元素 pt 压入栈 pStack
 38 int Pop( ArrStack *pStack, ElemType *pt );      ///将栈顶元素出栈到 pt
 39 int GetTop( ArrStack *pStack, ElemType *pt );   ///获取栈顶元素到 pt
 40 void ForEachStack( ArrStack *pStack, void (*func)(ElemType *pt) );      ///从栈底到栈顶的每个元素依次执行 func 函数
 41 void ReForEachStack( ArrStack *pStack, void (*func)(ElemType *pt) );    ///从栈顶到栈底的每个元素依次执行 func 函数
 42 
 43 
 44 //栈方法实现
 45 
 46 /**
 47 * @brief 创建一个大小为 nSize 的栈
 48 *
 49 * @param nSize 栈的初始大小
 50 *
 51 * @return 返回指向创建的栈的指针
 52 *
 53 * @note nSize 初始大小需大于0
 54 */
 55 ArrStack *CreateStack( int nSize )
 56 {
 57     //根据栈结构创建一个栈
 58     ArrStack *pStack = (ArrStack *)malloc( sizeof(ArrStack) );
 59 
 60     //申请栈初始空间
 61     pStack->btm = (ElemType *)calloc( nSize, sizeof(ElemType) );
 62 
 63     //令栈顶指向栈底元素
 64     pStack->top = &pStack->btm[0];
 65 
 66     //初始化栈高度为 0
 67     pStack->height = 0;
 68 
 69     //初始化栈大小为初始大小
 70     pStack->size = nSize;
 71 
 72     return pStack;
 73 }
 74 
 75 /**
 76 * @brief 销毁栈 pStack
 77 *
 78 * @param pStack 指向待销毁的栈的指针
 79 *
 80 * @return void
 81 */
 82 void DestroyStack( ArrStack *pStack )
 83 {
 84     //释放栈内元素
 85     free( pStack->btm );
 86 
 87     //释放栈
 88     free( pStack );
 89 }
 90 
 91 /**
 92 * @brief 清空栈内元素
 93 *
 94 * @param pStack 指向待清空元素的栈的指针
 95 *
 96 * @return void
 97 */
 98 void ClearStack( ArrStack *pStack )
 99 {
100     //令栈顶指向栈底
101     pStack->top = &pStack->btm[0];
102 
103     //将栈高度置为 0
104     pStack->height = 0;
105 }
106 
107 /**
108 * @brief 获取栈 pStack 的高度
109 *
110 * @param pStack 指向待获取高度的栈的指针
111 *
112 * @param 返回当前栈的高度
113 */
114 int GetHeight( ArrStack *pStack )
115 {
116     return pStack->height;
117 }
118 
119 /**
120 * @brief 获取栈 pStack 的总容量
121 *
122 * @param pStack 指向待获取总容量的栈的指针
123 *
124 * @return 返回栈的当前总容量
125 */
126 int GetSize( ArrStack *pStack )
127 {
128     return pStack->size;
129 }
130 
131 /**
132 * @brief 检测栈 pStack 是否为空栈
133 *
134 * @param pStack 指向待检测的栈的指针
135 *
136 * @return 若栈为空, 则返回 TRUE, 否则返回 FALSE
137 */
138 int IsEmpty( ArrStack *pStack )
139 {
140     return pStack->height == 0 ? TRUE : FALSE;
141 }
142 
143 /**
144 * @brief 将元素 pt 压入栈 pStack
145 *
146 * @param pStack 指向待压入元素的栈的指针
147 * @param pt 指向待压入元素的指针
148 *
149 * @return 返回成功压入后栈的高度
150 */
151 int Push( ArrStack *pStack, ElemType *pt )
152 {
153     ///检测是否需要扩容
154     if( pStack->height == pStack->size )
155     {   //需要扩容
156 
157         //重新申请于原栈大小2倍大小的栈空间
158         ElemType *pe = (ElemType *)calloc( pStack->size * 2, sizeof(ElemType) );
159 
160         //将旧栈内容拷贝到新栈内容
161         memcpy( pe, pStack->btm, pStack->size * sizeof(ElemType) );
162 
163         //重置栈总容量大小
164         pStack->size = pStack->size * 2;
165 
166         //释放旧栈空间
167         free( pStack->btm );
168 
169         //将栈底指向新开辟的栈空间
170         pStack->btm = pe;
171 
172         //栈顶指向新栈最后一个元素
173         pStack->top = &pe[pStack->height-1];
174     }
175 
176     //将新元素压入栈
177     pStack->btm[pStack->height].x = pt->x;
178     pStack->btm[pStack->height].y = pt->y;
179 
180     //栈高度自增一
181     ++pStack->height;
182 
183     //栈顶指向最新栈元素
184     pStack->top = &pStack->btm[pStack->height-1];
185 
186     return pStack->height;
187 }
188 
189 /**
190 * @brief 将栈顶元素出栈 到 pt
191 *
192 * @param pStack 指向待弹出元素的栈的指针
193 * @param pt 指向接收弹出的元素的指针
194 *
195 * @return 出栈成功则返回出栈后栈的高度, 否则返回 -1
196 */
197 int Pop( ArrStack *pStack, ElemType *pt )
198 {
199     ///是否为空栈
200     if( pStack->height == 0 )
201         return -1;
202 
203     //将栈顶元素赋值到 pt
204     pt->x = pStack->top->x;
205     pt->y = pStack->top->y;
206 
207     //栈高度减一
208     --pStack->height;
209 
210     //栈顶指向栈顶元素的上一个元素
211     pStack->top = &pStack->btm[pStack->height-1];
212 
213     return pStack->height;
214 }
215 
216 /**
217 * @brief 获取栈顶元素到 pt
218 *
219 * @param pStack 指向待弹出元素的栈的指针
220 * @param pt 指向接收弹出的元素的指针
221 *
222 * @return 获取成功则返回栈顶元素的位置, 否则返回 -1
223 *
224 * @note 元素位置由 0 计起
225 */
226 int GetTop( ArrStack *pStack, ElemType *pt )
227 {
228     pt->x = pStack->top->x;
229     pt->y = pStack->top->y;
230 
231     return pStack->height - 1;
232 }
233 
234 /**
235 * @brief 从栈底到栈顶的每个元素依次执行 func 函数
236 *
237 * @param pStack 指向待处理的栈的指针
238 * @param func 需要执行的函数的指针
239 *
240 * @return void
241 */
242 void ForEachStack( ArrStack *pStack, void (*func)(ElemType *pt) )
243 {
244     int i = 0;
245     for( i = 0; i <  pStack->height; ++i )
246     {
247         func( &pStack->btm[i] );
248     }
249 }
250 
251 /**
252 * @brief 从栈顶到栈底的每个元素依次执行 func 函数
253 *
254 * @param pStack 指向待处理的栈的指针
255 * @param func 需要执行的函数的指针
256 *
257 * @return void
258 */
259 void ReForEachStack( ArrStack *pStack, void (*func)(ElemType *pt) )
260 {
261     int i = pStack->height - 1;
262     for( i; i >= 0; --i )
263     {
264         func( &pStack->btm[i] );
265     }
266 }
267 
268 //测试
269 
270 void display( ElemType *pt )
271 {
272     printf( "(%d,%d) ", pt->x, pt->y );
273 }
274 
275 int main()
276 {
277     ///测试创建初始大小为 5 的栈
278     ArrStack *psk = CreateStack( 5 );
279 
280     ///测试 IsEmpty、GetSize、GetHeight
281     if( IsEmpty(psk) == TRUE )
282         printf( "Stack Size=%d, Stack Height=%d\n", GetSize(psk), GetHeight(psk) );
283 
284     ElemType pt;
285 
286     int i = 0;
287     ///测试Push, 向栈内压入8个元素
288     printf( "\n向栈内压入8个元素后:\n" );
289     for( i = 0; i < 8; ++i )
290     {
291         pt.x = pt.y = i;
292         Push( psk, &pt );
293     }
294     //输出压入8个元素后的栈状态
295     printf( "Is empty = %d\n", IsEmpty(psk) );
296     printf( "Stack size = %d\n", GetSize(psk) );
297     printf( "Stack height = %d\n", GetHeight(psk) );
298 
299     ///测试 ForEachStack、ReForEachStack
300     printf( "\n测试 ForEachStack、ReForEachStack:\n" );
301     ForEachStack( psk, display );
302     putchar('\n');
303     ReForEachStack( psk, display );
304     putchar('\n');
305 
306     ///测试getTop
307     GetTop( psk, &pt );
308     printf( "\n栈顶元素为: (%d,%d)\n", pt.x, pt.y );
309 
310     ///测试 Pop
311     Pop( psk, &pt );
312     printf( "\nPop弹出的元素为(%d,%d), 弹出后栈高:%d\n", pt.x, pt.y, GetHeight(psk) );
313     Pop( psk, &pt );
314     printf( "\nPop弹出的元素为(%d,%d), 弹出后栈高:%d\n", pt.x, pt.y, GetHeight(psk) );
315 
316     ///测试Push
317     pt.x = pt.y = 100;
318     Push( psk, &pt );
319     printf( "\nPop压入的元素为(%d,%d), 压入后栈高:%d\n", pt.x, pt.y, GetHeight(psk) );
320 
321     ///执行全面出栈操作
322     printf( "\n执行全面出栈:\n" );
323     int n = GetHeight(psk);
324     for( i = 0; i < n; ++i )
325     {
326         Pop( psk, &pt );
327         printf( "Pop弹出的元素为(%d,%d), 弹出后栈高:%d\n", pt.x, pt.y, GetHeight(psk) );
328     }
329 
330     ///销毁栈
331     DestroyStack( psk );
332 
333     return 0;
334 }

 测试结果:

 

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