一個可以自動擴容的順序結構的棧 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