C语言 栈 顺序结构 实现
2013-10-29 13:26 wid 阅读(1320) 评论(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 或程序缺陷, 请留言反馈, 谢谢。