返回首页 一起talk C栗子吧

一起talk C栗子吧(第十七回:C语言实例--栈二)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例。闲话休提, 言归正转。让我们一起talk C栗子吧!

看官们,上一回中咱们说的是栈和特点和基本操作,最后通过顺序存储的方式实现了栈,这一回咱们继续 说栈,不过咱们这一回说的是栈的链式存储方式。

在代码中通过双向链表来实现栈的链式存储。入栈操作沿着表头到表尾的方向进行,出栈操作与其正好相 反(就把它当作双向链表的一个使用实例吧)。栈的结点可以看作是链表中的结点,对栈的操作,可以看 作是在链表中进行插入或者删除结点操作。只不过插入或者删除时要遵循栈“先进后出"的特点。栈的类型 中增加了一个size成员,可以通过它方便地得出栈的长度。与栈的顺序存储方式相比,多了一个销毁栈的 功能。因为栈中的空间都是动态分配得来的,每次入栈操作都会分配一块内存空间,与其相反,每次出栈 操作都会把内存空间释放掉。但是在实际程序中入栈和出栈并不是成对出现的,也就是说,如果使用完栈 后,没有通过出栈操作来释放动态空间,那么就会造成内存泄漏。所以我增加了销毁栈的功能,以方便在 程序的最后检查栈中动态分配来的空间是否被释放。

栈的链式存储与栈的顺序存储相比,最大的优点就是不需要事先知道栈的长度,只要内存空间足够大就能 存放足够多的元素到栈中。不过,它也有缺点,那就是入栈和出栈操作要复杂,而且效率低。总之,在实 际的程序中如果事先知道栈的长度,可以使用栈的顺序存储,如果与事先不知道栈的长度,那么可以使用 栈的链式存储,这样比较灵活一些。

看官们,详细的代码如下,大家可以参考:

     1  /* **************************
     2   * Head file of Stack
     3   * *************************/
     4  #ifndef STACK_H
     5  #define STACK_H
     6  
     7  #include<stdio.h>
     8  #include<stdlib.h>
     9  
    10  #define SUCCESS 0
    11  #define FAILE 1
    12  
    13  typedef struct _StackElmt
    14  {
    15      int data;
    16      struct _StackElmt *pre;
    17      struct _StackElmt *next;
    18  }StackElmt; //把int当作栈中元素的类型,实际中可以使用其它的类型或者自己定义一个类型
    19  
    20  typedef struct _Stack{
    21      StackElmt *base; //栈底指针
    22      StackElmt *top;  //栈顶指针,它指向的区域存放StackElmt类型的值
    23      int size;        //方便统计栈的长度
    24  }Stack;
    25  
    26  //声明函数原型,这里有入栈和出栈操的函数
    27  int StackInit(Stack *s);
    28  int StackPrint(Stack *s);
    29  int StackPush(Stack *s, int e);
    30  int StackPop(Stack *s, int *e);
    31  int StackDestroy(Stack *s);
    32  
    33  #endif /*STACK_H*/
     1  /* **************************
     2   * Soure file of Stack
     3   * *************************/
     4  
     5  #include"Ex015_Stack2.h"
     6  
     7  //实现List的函数,为了方便,放到了主函数所在的文件中,最好是单独建立实现函数的源文件
     8  //
     9  //初始化中栈
    10  int StackInit(Stack *s)
    11  {
    12      if(NULL == s)
    13          return FAILE;
    14  
    15      s->top = s->base = NULL;
    16      s->size = 0;
    17  
    18      return SUCCESS;
    19  }
    20  
    21  //输出栈中存放的元素
    22  int StackPrint(Stack *s)
    23  {
    24      int index = 0;
    25      StackElmt *t = NULL;
    26  
    27      if(NULL == s)
    28          return FAILE;
    29  
    30      if(s->size == 0)
    31      {
    32          printf("the Stack is empty,there is not any element \n");
    33          return FAILE;
    34      }
    35  
    36      t = s->base;
    37      while(NULL != t)
    38      {
    39          printf("%d  ",t->data);
    40          t = t->next;
    41      }
    42  
    43      printf("\n ");
    44  
    45      return SUCCESS;
    46  }
    47  
    48  //入栈函数,top指向栈顶,每次push操作都会分配一个空间,top永远指向该空间
    49  int StackPush(Stack *s, int e)
    50  {
    51      StackElmt *node = NULL;
    52  
    53      if(NULL == s)
    54          return FAILE;
    55  
    56      node = (StackElmt *)malloc( sizeof(StackElmt) );
    57  
    58      if(NULL != node)
    59      {
    60          if(NULL == s->base)
    61          {
    62              s->top = s->base = node;
    63              node->pre = NULL;
    64          }
    65          else
    66          {
    67              (s->top)->next = node;
    68              node->pre = s->top;
    69              s->top = node; //相当于顺序存储中的top++
    70          }
    71  
    72          node->data = e;
    73          node->next = NULL;
    74          (s->size)++;
    75  
    76          return SUCCESS;
    77      }
    78      else
    79          return FAILE;
    80  }
    81  
    82  //出栈函数,先把top指向的元素出栈,然后释放top指向的空间
    83  int StackPop(Stack *s, int *e)
    84  {
    85      StackElmt *t = NULL;
    86  
    87      if(NULL == s)
    88          return FAILE;
    89  
    90      if(s->size == 0)
    91      {
    92          printf("the Stack is empty \n");
    93          return FAILE;
    94      }
    95  
    96      *e = (s->top)->data ;
    97      t = (s->top)->pre;
    98      free(s->top);
    99      s->top = t; //相当于top--
   100  
   101      if(s->size == 1) //最后一个元素出栈时,base和top都为NULL
   102          s->base = s->top;
   103  
   104      (s->size)--;
   105  
   106      return SUCCESS;
   107  }
   108  
   109  //栈销毁函数,因为有动态分配的空间,如果不执行出栈操作,要把栈destroy
   110  int StackDestroy(Stack *s)
   111  {
   112      int t = 0;
   113      int result = 0;
   114  
   115      if(NULL == s)
   116          return FAILE;
   117  
   118      while(NULL != (s->base) )
   119          result = StackPop(s,&t);
   120  
   121      return result;
   122  }
   123  
   124  int main()
   125  {
   126      int i = 0;
   127      int e = 0;
   128      Stack stack ;
   129  
   130      if( SUCCESS == StackInit(&stack) )
   131          StackPrint(&stack);
   132  
   133      StackPush(&stack,7);
   134      StackPrint(&stack);
   135  
   136      StackPop(&stack,&e);
   137      printf("%d is poped \n",e);
   138  
   139      while(i++ < 5)
   140      {
   141          if( SUCCESS == StackPush(&stack,i) )
   142              printf("%d is pushed \n",i);
   143          else
   144              printf("push failed \n");
   145      }
   146  
   147      while(i-- > 0)
   148      {
   149          if( SUCCESS == StackPop(&stack,&e) )
   150              printf("%d is poped \n",e);
   151          else
   152              printf("pop failed \n");
   153      }
   154  
   155      if( SUCCESS == StackDestroy)
   156          printf("Stack destroy successfully  \n");
   157      else
   158          printf("Stack need not to destroy  \n");
   159  
   160  }

各位看官,关于栈的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解。