• 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
    ", GetSize(psk), GetHeight(psk) );
    283 
    284     ElemType pt;
    285 
    286     int i = 0;
    287     ///测试Push, 向栈内压入8个元素
    288     printf( "
    向栈内压入8个元素后:
    " );
    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
    ", IsEmpty(psk) );
    296     printf( "Stack size = %d
    ", GetSize(psk) );
    297     printf( "Stack height = %d
    ", GetHeight(psk) );
    298 
    299     ///测试 ForEachStack、ReForEachStack
    300     printf( "
    测试 ForEachStack、ReForEachStack:
    " );
    301     ForEachStack( psk, display );
    302     putchar('
    ');
    303     ReForEachStack( psk, display );
    304     putchar('
    ');
    305 
    306     ///测试getTop
    307     GetTop( psk, &pt );
    308     printf( "
    栈顶元素为: (%d,%d)
    ", pt.x, pt.y );
    309 
    310     ///测试 Pop
    311     Pop( psk, &pt );
    312     printf( "
    Pop弹出的元素为(%d,%d), 弹出后栈高:%d
    ", pt.x, pt.y, GetHeight(psk) );
    313     Pop( psk, &pt );
    314     printf( "
    Pop弹出的元素为(%d,%d), 弹出后栈高:%d
    ", pt.x, pt.y, GetHeight(psk) );
    315 
    316     ///测试Push
    317     pt.x = pt.y = 100;
    318     Push( psk, &pt );
    319     printf( "
    Pop压入的元素为(%d,%d), 压入后栈高:%d
    ", pt.x, pt.y, GetHeight(psk) );
    320 
    321     ///执行全面出栈操作
    322     printf( "
    执行全面出栈:
    " );
    323     int n = GetHeight(psk);
    324     for( i = 0; i < n; ++i )
    325     {
    326         Pop( psk, &pt );
    327         printf( "Pop弹出的元素为(%d,%d), 弹出后栈高:%d
    ", pt.x, pt.y, GetHeight(psk) );
    328     }
    329 
    330     ///销毁栈
    331     DestroyStack( psk );
    332 
    333     return 0;
    334 }

     测试结果:

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

  • 相关阅读:
    YbSoftwareFactory 代码生成插件【二十】:DynamicObject的序列化
    YbSoftwareFactory 代码生成插件【十九】:实体类配合数据库表字段进行属性扩展的小技巧
    YbSoftwareFactory 代码生成插件【十八】:树形结构下的查询排序的数据库设计
    YbSoftwareFactory 代码生成插件【十七】:先进的权限模型体系设计
    YbSoftwareFactory 代码生成插件【十六】:Web 下灵活、强大的审批流程实现(含流程控制组件、流程设计器和表单设计器)
    YbSoftwareFactory 代码生成插件【十五】:Show 一下最新的动态属性扩展功能与键值生成器功能
    YbSoftwareFactory 代码生成插件【十四】:通过 DynamicLinq 简单实现 N-Tier 部署下的服务端数据库通用分页
    YbSoftwareFactory 代码生成插件【十三】:Web API 的安全性
    Navicat 密码加密算法
    GitHub开源的超棒后台管理面板
  • 原文地址:https://www.cnblogs.com/mr-wid/p/3394125.html
Copyright © 2020-2023  润新知