C語言 棧 順序結構 實現

一個可以自動擴容的順序結構的棧 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 或程序缺陷, 請留言反饋, 謝謝。                                                                                                                                                                                                                                                                                                                                                            spa

相關文章
相關標籤/搜索