数据结构学习笔记(3)——栈

1 栈得定义

栈(Stack):具备必定操做约束的线性表
只在一端(栈顶,Top)作 插入、删除web

  • 插入数据:入栈(Push)
  • 删除数据:出栈(Pop)
  • 后入先出:Last In First Out(LIFO)

栈的抽象数据类型

类型名称: 栈(Stack)
数据对象集: 一个有0个或多个元素的有穷线性表。
操做集: 长度为MaxSize的堆栈S  Stack,堆栈元素item  ElementType数组

  1. Stack CreateStack( int MaxSize ): 生成空堆栈,其最大长度为MaxSize;
  2. int IsFull( Stack S, int MaxSize ):判断堆栈S是否已满;
  3. void Push( Stack S, ElementType x ):将元素x压入堆栈;
  4. int IsEmpty ( Stack S ):判断堆栈S是否为空;
  5. ElementType Pop( Stack S ):删除并返回栈顶元素;

在这里插入图片描述
Push 和 Pop 能够穿插交替进行;
按照操做系列
(1)Push(S,A), Push(S,B),Push((S,C),Pop(S),Pop(S),Pop(S)
堆栈输出是? CBA
(2) 而Push(S,A), Pop(S),Push(S,B),Push((S,C),Pop(S),Pop(S)
堆栈输出是? ACBsvg

2 栈的顺序存储

栈的顺序存储结构一般由一个一维数组和一个记录栈顶元素位置的变量组成。spa

2.1 结构:

typedef int Position;
    struct SNode {
        ElementType *Data; /* 存储元素的数组 */
        Position Top;      /* 栈顶指针 */
        int MaxSize;       /* 堆栈最大容量 */
    };
    typedef struct SNode *Stack;

2.2 创造空栈

Stack CreateStack( int MaxSize )
    {
        Stack S = (Stack)malloc(sizeof(struct SNode));
        S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
        S->Top = -1;
        S->MaxSize = MaxSize;
        return S;
    }

2.3 入栈指针

int IsFull( Stack S )
    {
        return (S->Top == S->MaxSize-1);
    }
     
    void Push( Stack S, ElementType X )
    {
        if ( IsFull(S) ) {
            printf("堆栈满");
            return false;
        }
        else {
            S->Data[++(S->Top)] = X;
            return true;
        }
    }

2.4 出栈(pop)code

int IsEmpty( Stack S )
    {
        return (S->Top == -1);
    }
     
    ElementType Pop( Stack S )
    {
        if ( IsEmpty(S) ) {
            printf("堆栈空");
            return ERROR; /* ERROR是ElementType的特殊值,标志错误 */
        }
        else 
            return ( S->Data[(S->Top)--] );
    }

3 两栈共享空间

两个栈分别从数组的两头开始向中间生长;当两个栈的栈顶指针相遇时,表示两个栈都满了。xml

3.1 结构

#define MaxSize <存储数据元素的最大个数>
struct DStack {
 ElementType Data[MaxSize]; 
 int Top1; /* 堆栈1的栈顶指针 */ 
 int Top2; /* 堆栈2的栈顶指针 */
} S;
S.Top1 = -1; 
S.Top2 = MaxSize;

3.2 入栈

void Push( struct DStack *PtrS, ElementType item, int Tag )
{ /* Tag做为区分两个堆栈的标志,取值为1和2 */
 if ( PtrS->Top2 – PtrS->Top1 == 1) { /*堆栈满*/
printf(“堆栈满”); return ;
 }
 if ( Tag == 1 ) /* 对第一个堆栈操做 */
 PtrS->Data[++(PtrS->Top1)] = item;
 else /* 对第二个堆栈操做 */
 PtrS->Data[--(PtrS->Top2)] = item;
}

3.3 出栈

ElementType Pop( struct DStack *PtrS, int Tag )
{ /* Tag做为区分两个堆栈的标志,取值为1和2 */
 if ( Tag == 1 ) { /* 对第一个堆栈操做 */
 if ( PtrS->Top1 == -1 ) { /*堆栈1空 */
 printf(“堆栈1空”); return NULL;
 } else return PtrS->Data[(PtrS->Top1)--];
 } else { /* 对第二个堆栈操做 */
 if ( PtrS->Top2 == MaxSize ) { /*堆栈2空 */
 printf(“堆栈2空”); return NULL;
 } else return PtrS->Data[(PtrS->Top2)++];
}
}

4 栈的链式存储实现

栈的链式存储结构实际上就是一个单链表,叫作链栈。插入和删除操做只能在链栈的栈顶进行。对象

4.1 结构

typedef struct SNode *PtrToSNode;
    struct SNode {
        ElementType Data;
        PtrToSNode Next;
    };
    typedef PtrToSNode Stack;

4.2 建立

Stack CreateStack( ) 
    { /* 构建一个堆栈的头结点,返回该结点指针 */
        Stack S;
     
        S = (Stack)malloc(sizeof(struct SNode));
        S->Next = NULL;
        return S;
    }

4.3 入栈

int IsEmpty ( Stack S )
    { /* 判断堆栈S是否为空,如果返回true;不然返回false */
        return ( S->Next == NULL );
    }
     
    void Push( Stack S, ElementType X )
    { /* 将元素X压入堆栈S */
        PtrToSNode TmpCell;
     
        TmpCell = (PtrToSNode)malloc(sizeof(struct SNode));
        TmpCell->Data = X;
        TmpCell->Next = S->Next;
        S->Next = TmpCell;
        return true;
    }

4.4 出栈

ElementType Pop( Stack S )  
    { /* 删除并返回堆栈S的栈顶元素 */
        PtrToSNode FirstCell;
        ElementType TopElem;
     
        if( IsEmpty(S) ) {
            printf("堆栈空"); 
            return ERROR;
        }
        else {
            FirstCell = S->Next; 
            TopElem = FirstCell->Data;
            S->Next = FirstCell->Next;
            free(FirstCell);
            return TopElem;
        }
    }