栈及其应用 - C语言实现(摘自数据结构与算法分析 C语言描述)

一、概述:

栈(stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈的顶(top)。对栈的基本操作有Push(进栈)和Pop(出栈),前者相当于插入,后者则是删除最后插入的元素。

栈有时又叫做LIFO(后进先出)表。在图1中描述的模型只象征着Push是输入操作而Pop和Top是输出操作。


图1 栈模型:通过Push向栈输入,通过Pop从栈输出

二、实现

1. 栈的链表实现

文件名:stack_list.h

  1. #ifndef _STACK_LIST_H  
  2. #define _STACK_LIST_H  
  3.   
  4. #define ElementType int  
  5. struct Node;  
  6. typedef struct Node *PtrToNode;  
  7. typedef PtrToNode Stack;  
  8.   
  9. int IsEmpty( Stack S );  
  10. Stack CreateStack( void );  
  11. void DisposeStack( Stack S );  
  12. void MakeEmpty( Stack S );  
  13. void Push( ElementType X, Stack S );  
  14. ElementType Top( Stack S );  
  15. void Pop( Stack S );  
  16.   
  17. #endif /* _STACK_LIST_H */  
文件名:stack_list.c
  1. #include "stack_list.h"  
  2. #include "fatal.h"  
  3. struct Node  
  4. {  
  5.   ElementType Element;  
  6.   PtrToNode Next;  
  7. };  
  8.   
  9. int  
  10. IsEmpty( Stack S )  
  11. {  
  12.   return S->Next == NULL;  
  13. }  
  14.   
  15. Stack  
  16. CreateStack( void )  
  17. {  
  18.   Stack S;  
  19.   
  20.   S = malloc( sizeofstruct Node ) );  
  21.   if( S == NULL )  
  22.     FatalError( "Out of space!!!" );  
  23.   S->Next = NULL;  
  24.   MakeEmpty( S );  
  25.   return S;  
  26. }  
  27.   
  28. void  
  29. MakeEmpty( Stack S )  
  30. {  
  31.   if( S == NULL )  
  32.     Error( "Must use CreateStack first" );  
  33.   else  
  34.     while( !IsEmpty( S ) )  
  35.       Pop( S );  
  36. }  
  37.   
  38. void  
  39. Push( ElementType X, Stack S )  
  40. {  
  41.   PtrToNode TmpCell;  
  42.   
  43.   TmpCell = malloc( sizeofstruct Node ) );  
  44.   if( TmpCell == NULL )  
  45.     FatalError( "Out of space!!!" );  
  46.   else  
  47.   {  
  48.     TmpCell->Element = X;  
  49.     TmpCell->Next = S->Next;  
  50.     S->Next = TmpCell;  
  51.   }  
  52. }  
  53.   
  54. ElementType  
  55. Top( Stack S )  
  56. {  
  57.   if( !IsEmpty( S ) )  
  58.     return S->Next->Element;  
  59.   Error( "Empty stack" );  
  60.   return 0;  
  61. }  
  62.   
  63. void  
  64. Pop(Stack S )  
  65. {  
  66.   PtrToNode FirstCell;  
  67.   if( IsEmpty( S ) )  
  68.     Error( "Empty Stack" );  
  69.   else  
  70.   {  
  71.     FirstCell = S->Next;  
  72.     S->Next = S->Next->Next;  
  73.     free( FirstCell );  
  74.   }  
  75. }  
文件名:main.c
  1. #include <stdio.h>  
  2. #include "stack_list.h"  
  3.   
  4. int main()  
  5. {  
  6.   Stack S;  
  7.   int n, num, m;  
  8.   int i;  
  9.   S = CreateStack();  
  10.   printf( "Initialization complete.\n" );  
  11.   printf( "Please input the number of elements in the stack:\n" );  
  12.   scanf( "%d", &n );  
  13.   printf( "Please input %d elements push into stack:\n", n );  
  14.   for(i = 0; i < n; i++ )  
  15.   {  
  16.     scanf( "%d", &num );  
  17.     Push( num, S );  
  18.   }  
  19.   printf( "Please input the numbers you want pop out from the stack(no more than:%d)\n", n );  
  20.   scanf( "%d", &n );  
  21.   printf( "Pop out from the stack %d elements in turns:\n", n );  
  22.   for( i = 0; i < n; i++ )  
  23.   {  
  24.     m = Top( S );  
  25.     Pop( S );  
  26.     printf( "%3d",m );  
  27.   }  
  28.   printf( "\n" );  
  29.   return 0;  
  30. }  


2. 栈的数组实现

文件名:stack_array.h

  1. #ifndef _STACK_ARRARY_H  
  2. #define _STACK_ARRARY_H  
  3. struct StackRecord;  
  4. typedef struct StackRecord *Stack;  
  5.   
  6. #define ElementType int  
  7.   
  8. int IsEmpty( Stack S );  
  9. int IsFull( Stack S );  
  10. Stack CreateStack( int MaxElements );  
  11. void DisposeStack( Stack S );  
  12. void MakeEmpty( Stack S );  
  13. void Push( ElementType X, Stack S );  
  14. ElementType Top( Stack S );  
  15. void Pop( Stack S );  
  16. ElementType TopAndPop( Stack S );  
  17.   
  18.   
  19. #endif  /* _STACK_ARRARY_H */  

文件名:stack_array.c

  1. #include "stack_array.h"  
  2. #include "fatal.h"  
  3.   
  4. #define EmptyTOS ( -1 )  
  5. #define MinStackSize ( 5 )  
  6.   
  7. struct StackRecord  
  8. {  
  9.     int Capacity;  
  10.     int TopOfStack;  
  11.     ElementType *Array;  
  12. };  
  13.   
  14. Stack  
  15. CreateStack( int MaxElements )  
  16. {  
  17.   Stack S;  
  18.   
  19.   if( MaxElements < MinStackSize )  
  20.     Error( "Stack size is too small" );  
  21.   
  22.   S = malloc( sizeofstruct StackRecord ) );  
  23.   if( S == NULL )  
  24.     FatalError( "Out of space!!!" );  
  25.   
  26.   S->Array = malloc( sizeof( ElementType ) * MaxElements );  
  27.   if( S->Array == NULL )  
  28.     FatalError( "Out of space!!!" );  
  29.   S->Capacity = MaxElements;  
  30.   MakeEmpty( S );  
  31.   
  32.   return S;  
  33. }  
  34.   
  35. void  
  36. DisposeStack( Stack S )  
  37. {  
  38.   if( S != NULL )  
  39.   {  
  40.     free( S-> Array );  
  41.     free( S );  
  42.   }  
  43. }  
  44.   
  45. int  
  46. IsEmpty( Stack S )  
  47. {  
  48.   return S->TopOfStack == EmptyTOS;  
  49. }  
  50.   
  51. void  
  52. MakeEmpty( Stack S )  
  53. {  
  54.   S->TopOfStack = EmptyTOS;  
  55. }  
  56.   
  57. void  
  58. Push( ElementType X, Stack S )  
  59. {  
  60.   if( IsFull( S ) )  
  61.     Error( "Full Stack" );  
  62.   else  
  63.     S->Array[ ++S->TopOfStack ] = X;  
  64. }  
  65.   
  66. int  
  67. IsFull( Stack S )  
  68. {  
  69.     return S->TopOfStack == S->Capacity - 1;  
  70. }  
  71.   
  72. ElementType  
  73. Top( Stack S )  
  74. {  
  75.   if( !IsEmpty( S ) )  
  76.     return S->Array[ S->TopOfStack ];  
  77.   Error( "Empty Stack" );  
  78.   return 0;                             /* Return value used to avoid 
  79.                                          * warning */  
  80. }  
  81.   
  82. void  
  83. Pop( Stack S )  
  84. {  
  85.   if( IsEmpty( S ) )  
  86.     Error( "Empty Stack" );  
  87.   else  
  88.     S->TopOfStack--;  
  89. }  
  90.   
  91. ElementType  
  92. TopAndPop( Stack S )  
  93. {  
  94.   if( !IsEmpty( S ) )  
  95.     return S->Array[ S->TopOfStack-- ];  
  96.   Error( "Empty Stack" );  
  97.   return 0;                             /* Return value used to avoid 
  98.                                          * warning */  
  99. }  

文件名:main.c
  1. #include <stdio.h>  
  2. #include "stack_array.h"  
  3. #include "fatal.h"  
  4.   
  5. int main()  
  6. {  
  7.   Stack S;  
  8.   int n, num, m;  
  9.   int i;  
  10.   S = CreateStack( 10 );  
  11.   printf( "Initialization complete.\n" );  
  12.   printf( "Please input the number of elements in the stack:\n" );  
  13.   scanf( "%d", &n );  
  14.   printf( "Please input %d elements push into stack:\n", n );  
  15.   for( i = 0; i < n; i++ )  
  16.   {  
  17.     scanf( "%d", &num );  
  18.     Push( num, S );  
  19.   }  
  20.   printf( "Top of the stack:%d\n", Top( S ) );  
  21.   printf( "Please input the numbers you want pop out from the stack(no more than %d):\n", n );  
  22.   scanf( "%d", &n );  
  23.   printf( "Pop out from the stack %d elements in turns:\n", n );  
  24.   for( i = 0; i < n; i++ )  
  25.   {  
  26.     m = TopAndPop( S );  
  27.     printf( "%3d", m );  
  28.   }  
  29.   printf( "\n" );  
  30.   return 0;  
  31. }  

附录:上述代码中用到了Error、FatalError等函数,其实现如下(即fatal.h文件):

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. #define Error( Str )        FatalError( Str )  
  5. #define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 )  


三、应用

1. 平衡符号:

编译器检查你的程序的语法错误,但是常常由于缺少一个符号(如遗漏一个花括号或是注释起始符)引起编译器列出上百行的诊断,而真正的错误并没有找出。
在这种情况下,一个有用的工具就是检验是否每件事情都能成对出现的一个程序。于是,每一个右花括号、右方括号及右圆括号必然对应其相应的左括号。序列“[()]”是合法的,但“[(])”是错误的。显然,不值得为此编写一个大型程序,事实上检验这些事情是很容易的。为简单起见,我们就圆括号、方括号和花括号进行检验并忽略出现的任何其他字符。
这个简单的算法用到一个栈,叙述如下:
做一个空栈。读入字符直到文件尾。如果字符是一个开放符号,则将其推入栈中。如果字符是一个封闭符号,则当栈空时报错。否则,将栈元素弹出。如果弹出的符号不是对应的开放符号,则报错。在文件尾,如果栈非空则报错。
算法实现:
  1. bool  
  2. balance( char ch, Stack S )  
  3. {  
  4.   switch( ch ) {  
  5.     case '(':  
  6.     case '[':  
  7.     case '{':  
  8.       Push( ch, S );  
  9.       break;  
  10.     case ')':  
  11.       if( IsEmpty( S ) || Top( S ) != '(' )  
  12.       {  
  13.         return false;  
  14.       }  
  15.       Pop( S );  
  16.       break;  
  17.     case ']':  
  18.       if( IsEmpty(S) || Top(S) != '[' )  
  19.       {  
  20.         return false;  
  21.       }  
  22.       Pop( S );  
  23.       break;  
  24.     case '}':  
  25.       if( IsEmpty( S ) || Top( S ) != '{' )  
  26.       {  
  27.         return false;  
  28.       }  
  29.       Pop( S );  
  30.       break;  
  31.     default:  
  32.       break;  
  33.   }  
  34.   return true;  
  35. }  

2. 后缀表达式

3. 中缀到后缀的转换

4. 函数调用


附录:上述代码中用到了Error、FatalError等函数,其实现如下(即fatal.h文件):
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. #define Error( Str )        FatalError( Str )  
  5. #define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 ) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值