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

来源:互联网 发布:一建培训班哪家好 知乎 编辑:程序博客网 时间:2024/04/29 18:12

一、概述:

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

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


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

二、实现

1. 栈的链表实现

文件名:stack_list.h

#ifndef _STACK_LIST_H#define _STACK_LIST_H#define ElementType intstruct Node;typedef struct Node *PtrToNode;typedef PtrToNode Stack;int IsEmpty( Stack S );Stack CreateStack( void );void DisposeStack( Stack S );void MakeEmpty( Stack S );void Push( ElementType X, Stack S );ElementType Top( Stack S );void Pop( Stack S );#endif /* _STACK_LIST_H */
文件名:stack_list.c

#include "stack_list.h"#include "fatal.h"struct Node{  ElementType Element;  PtrToNode Next;};intIsEmpty( Stack S ){  return S->Next == NULL;}StackCreateStack( void ){  Stack S;  S = malloc( sizeof( struct Node ) );  if( S == NULL )    FatalError( "Out of space!!!" );  S->Next = NULL;  MakeEmpty( S );  return S;}voidMakeEmpty( Stack S ){  if( S == NULL )    Error( "Must use CreateStack first" );  else    while( !IsEmpty( S ) )      Pop( S );}voidPush( ElementType X, Stack S ){  PtrToNode TmpCell;  TmpCell = malloc( sizeof( struct Node ) );  if( TmpCell == NULL )    FatalError( "Out of space!!!" );  else  {    TmpCell->Element = X;    TmpCell->Next = S->Next;    S->Next = TmpCell;  }}ElementTypeTop( Stack S ){  if( !IsEmpty( S ) )    return S->Next->Element;  Error( "Empty stack" );  return 0;}voidPop(Stack S ){  PtrToNode FirstCell;  if( IsEmpty( S ) )    Error( "Empty Stack" );  else  {    FirstCell = S->Next;    S->Next = S->Next->Next;    free( FirstCell );  }}
文件名:main.c

#include <stdio.h>#include "stack_list.h"int main(){  Stack S;  int n, num, m;  int i;  S = CreateStack();  printf( "Initialization complete.\n" );  printf( "Please input the number of elements in the stack:\n" );  scanf( "%d", &n );  printf( "Please input %d elements push into stack:\n", n );  for(i = 0; i < n; i++ )  {    scanf( "%d", &num );    Push( num, S );  }  printf( "Please input the numbers you want pop out from the stack(no more than:%d)\n", n );  scanf( "%d", &n );  printf( "Pop out from the stack %d elements in turns:\n", n );  for( i = 0; i < n; i++ )  {    m = Top( S );    Pop( S );    printf( "%3d",m );  }  printf( "\n" );  return 0;}


2. 栈的数组实现

文件名:stack_array.h

#ifndef _STACK_ARRARY_H#define _STACK_ARRARY_Hstruct StackRecord;typedef struct StackRecord *Stack;#define ElementType intint IsEmpty( Stack S );int IsFull( Stack S );Stack CreateStack( int MaxElements );void DisposeStack( Stack S );void MakeEmpty( Stack S );void Push( ElementType X, Stack S );ElementType Top( Stack S );void Pop( Stack S );ElementType TopAndPop( Stack S );#endif  /* _STACK_ARRARY_H */

文件名:stack_array.c

#include "stack_array.h"#include "fatal.h"#define EmptyTOS ( -1 )#define MinStackSize ( 5 )struct StackRecord{    int Capacity;    int TopOfStack;    ElementType *Array;};StackCreateStack( int MaxElements ){  Stack S;  if( MaxElements < MinStackSize )    Error( "Stack size is too small" );  S = malloc( sizeof( struct StackRecord ) );  if( S == NULL )    FatalError( "Out of space!!!" );  S->Array = malloc( sizeof( ElementType ) * MaxElements );  if( S->Array == NULL )    FatalError( "Out of space!!!" );  S->Capacity = MaxElements;  MakeEmpty( S );  return S;}voidDisposeStack( Stack S ){  if( S != NULL )  {    free( S-> Array );    free( S );  }}intIsEmpty( Stack S ){  return S->TopOfStack == EmptyTOS;}voidMakeEmpty( Stack S ){  S->TopOfStack = EmptyTOS;}voidPush( ElementType X, Stack S ){  if( IsFull( S ) )    Error( "Full Stack" );  else    S->Array[ ++S->TopOfStack ] = X;}intIsFull( Stack S ){    return S->TopOfStack == S->Capacity - 1;}ElementTypeTop( Stack S ){  if( !IsEmpty( S ) )    return S->Array[ S->TopOfStack ];  Error( "Empty Stack" );  return 0;                             /* Return value used to avoid                                         * warning */}voidPop( Stack S ){  if( IsEmpty( S ) )    Error( "Empty Stack" );  else    S->TopOfStack--;}ElementTypeTopAndPop( Stack S ){  if( !IsEmpty( S ) )    return S->Array[ S->TopOfStack-- ];  Error( "Empty Stack" );  return 0;                             /* Return value used to avoid                                         * warning */}

文件名:main.c

#include <stdio.h>#include "stack_array.h"#include "fatal.h"int main(){  Stack S;  int n, num, m;  int i;  S = CreateStack( 10 );  printf( "Initialization complete.\n" );  printf( "Please input the number of elements in the stack:\n" );  scanf( "%d", &n );  printf( "Please input %d elements push into stack:\n", n );  for( i = 0; i < n; i++ )  {    scanf( "%d", &num );    Push( num, S );  }  printf( "Top of the stack:%d\n", Top( S ) );  printf( "Please input the numbers you want pop out from the stack(no more than %d):\n", n );  scanf( "%d", &n );  printf( "Pop out from the stack %d elements in turns:\n", n );  for( i = 0; i < n; i++ )  {    m = TopAndPop( S );    printf( "%3d", m );  }  printf( "\n" );  return 0;}

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

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


三、应用

1. 平衡符号:

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

2. 后缀表达式

3. 中缀到后缀的转换

4. 函数调用


附录:上述代码中用到了Error、FatalError等函数,其实现如下(即fatal.h文件):
#include <stdio.h>#include <stdlib.h>#define Error( Str )        FatalError( Str )#define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 )

备注:本文摘自《数据结构与算法分析 C语言描述 Mark Allen Weiss著》,代码经gcc编译测试通过。


附件下载:

http://download.csdn.net/detail/shuxiao9058/4212444#stack_array_20111229.tar.gz,

http://download.csdn.net/detail/shuxiao9058/4212446#stack_list_20111229.tar.gz,

http://download.csdn.net/detail/shuxiao9058/4212449#stack_balance_20111229.tar.gz

原创粉丝点击