来源:互联网 发布:淘宝简明英语语法教程 编辑:程序博客网 时间:2024/05/22 03:17

前言
本文在完成过程中,得到许多朋友的帮助,在此谢谢诸位。本人欢乐无限,技术有限,如有任何问题,欢迎各位不吝赐教。

1 栈ADT

  栈(stack)是限制插入和删除操作只能在一端进行的线性表。允许插入和删除的这一端称为栈顶(top),相对的另外一端称为栈底(bottom)。从定义中我们知道栈有两种基本操作:进栈(push,也称为入栈)和出栈(pop,也称为弹出)。进栈是指将新元素插入栈中,而出栈是删除最后进栈的元素。有时候需要得到栈顶元素,可以通过执行top函数返回。
  栈具有后进先出(Last In, First Out)的特性,因此又称为后进先出的表(LIFO)。

2 栈的实现

  栈有两种常见的实现方法:一是采用链表,二是采用数组实现。采用哪种方法好取决于具体应用。

2.1 栈的链表实现

  先给出用单链表实现的栈的模型,初始时栈为空:
1
  从这里我们可以看出栈的初态和单链表的初态一样,也就是说,栈的链表实现保留了头结点。
  如果我们依次将A1,A2,……,An进栈,这时栈的模型如下:
2
  好了,模型弄明白后其实进栈和出栈操作大家应该会有想法了,对,进栈其实就是在头结点后面插入新元素,如下push(x, S):
3
  出栈当然是要删除头结点后面的元素,如下pop(S):
4
  好了,大家看代码吧。首先Stackli.h:

typedef int ElementType;#ifndef STACKLI_H#define STACKLI_Hstruct Node;typedef struct Node *PtrToNode;typedef PtrToNode Stack;int isEmpty( Stack S );Stack createStack(  );void disposeStack( Stack S );void makeEmpty( Stack S );void push( ElementType x, Stack S );ElementType top( Stack S );void pop( Stack S );#endif

Fatal.h:

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

Stackli.c:

#include <stdlib.h>#include "Stackli.h"#include "Fatal.h"struct Node{    ElementType element;    PtrToNode   next;};int isEmpty( Stack S ){    return S->next == NULL;}Stack createStack(  ){    Stack S;    S = malloc( sizeof( struct Node ) );    if( S == NULL )        FatalError( "Out of space!!!" );    S->next = NULL;    return S;}void makeEmpty( Stack S ){    if( S == NULL )        Error( "Must use CreateStack first" );    else        while( !isEmpty( S ) )            pop( S );}void disposeStack( Stack S ){    makeEmpty( S );    free( S );}void push( 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;    }}ElementType top( Stack S ){    if( isEmpty( S ) )        Error( "Empty stack" );    return S->next->element;}void pop( 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 <stdlib.h>#include "Stackli.h"int main(int argc, char *argv[]) {    Stack S;    S = createStack( );    for(int i = 0; i < 5; i++ )        push( i, S );    while( !isEmpty( S ) ) {        printf( "%d\n", top( S ) );        pop( S );    }    disposeStack( S );    return 0;}

2.2 栈的数组实现

  如果在任何时候,你的程序中栈的大小都不会太大,则用数组实现栈可能是更好的方案。数组实现栈时,其数据结构包含两部分:栈的结构和栈的数组。如下图所示:
5
  中间显示的是栈的结构,它有三个成员:

  • capacity:int型变量,存储栈的容量。
  • topOfStack:int型变量,存储栈顶元素的下标,用来指示栈顶位置。空栈时为-1。
  • array:指针,指向栈的数组。

\
  上图中右面是栈的数组,它是一个动态数组。为了和抽象的栈的模型相对应,我们将数组画成竖的。所以,靠近上面的位置是栈顶,而array[0]为栈底(栈非空时)。
  至此,栈的数组实现应该水落石出了。首先是Stackar.h:

typedef int ElementType;#ifndef STACKAR_H#define STACKAR_Hstruct StackRecord;typedef struct StackRecord *Stack;int isEmpty( Stack S );int isFull( Stack S );Stack createStack( int maxElements );int size(Stack S);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

Fatal.h:

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

Stackar.c:

#include <stdlib.h>#include "Stackar.h"#include "Fatal.h"#define EmptyTOS ( -1 )#define MinStackSize ( 5 )struct StackRecord{    int capacity;    int topOfStack;    ElementType *array;};int isEmpty( Stack S ){    return S->topOfStack == EmptyTOS;}int isFull( Stack S ){    return S->topOfStack == S->capacity - 1;}Stack createStack( 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;}int size(Stack S){    return S->topOfStack + 1;}void makeEmpty( Stack S ){    S->topOfStack = EmptyTOS;}void disposeStack( Stack S ){    if( S != NULL ) {        free( S->array );        free( S );    }}void push( ElementType x, Stack S ){    if( isFull( S ) )        Error( "Full stack" );    S->array[ ++S->topOfStack ] = x;}ElementType top( Stack S ){    if( isEmpty( S ) )        Error( "Empty stack" );    return S->array[ S->topOfStack ];}void pop( Stack S ){    if( isEmpty( S ) )        Error( "Empty stack" );    S->topOfStack--;}ElementType topAndPop( Stack S ){    if( isEmpty( S ) )        Error( "Empty stack" );    return S->array[ S->topOfStack-- ];}

  测试程序main.c:

#include <stdio.h>#include <stdlib.h>#include "Stackar.h"int main(int argc, char *argv[]) {    Stack S;    S = createStack(15);    for(int i = 0; i < 10; i++ )        push( i, S );    printf("栈的大小为:%d\n", size(S));    while( !isEmpty( S ) ) {        printf( "%d\n", top( S ) );        pop( S );    }    disposeStack( S );    return 0;}
0 0
原创粉丝点击