数据结构—基础知识(六):栈

数据结构—基础知识(六):栈

栈的定义和特点

(stack)是限定仅在表尾进行插入或删除操作的线性表。对于栈来说,表尾段有其特殊含义称为栈顶(top),表头段称为栈底(bottom)。栈又称为后进先出(Last In First Out)的线性表,简称为LIFO结构。
数据结构—基础知识(六):栈_第1张图片

栈和一般线性表的区别:仅在于运算规则不同。

注:在程序设计中,如果需要按照保存数据时相反的顺序来使用数据,则可以利用栈来实现。

栈的表示和实现

顺序栈

  1. 顺序栈的定义:

    //-----顺序栈的存储结构-----
    #define MAXSIZE 100
    typedef struct
    {
        SELlemType *base;//栈底指针
        SELlemType *top;//栈顶指针
        int stacksize;//栈可用的最大容量
    }SqStack;
    

    注:base 为栈底指针,初始化完成后,栈底指针base 始终指向栈底的位置,若 base 的值为 NULL,则表明栈结构不存在。top为栈顶指针,其初值指向栈底。每当插入新的栈顶元素时,指针top 增 1;删除栈顶元素时,指针 top 减 1。因此,栈空时,top 和 base 的值相等,都指向栈底;栈非空时,top 始终指向栈顶元素的上一个位置。

    顺序栈中数据元素和栈指针之间的对应关系如下图:数据结构—基础知识(六):栈_第2张图片

  2. 顺序栈的初始化

    【算法步骤】

    • 为顺序栈动态分配一个最大容量为MAXSIZE的数组空间,使base指向这段空间的基地址,即栈底。

    • 栈顶指针top初始为base,表示栈为空。

    • stacksize置为栈的最大容量MAXSIZE。

      Status InitStack(SqStack &S)
      {//构造一个空栈S
          S.base=new SElemType[MAXSIZE];//为顺序栈动态分配一个最大容量为MAXSIZE的数组空间。
          if(!S.base) exit(OVERFLOW);//存储分配失败
          S.top=S.base;//top初始为base,空栈
          S.stacksize=MAXSIZE;//stacksize置为栈的最大容量MAXSIZE
          return OK;  
      }
      
  3. 顺序栈的入栈

    【算法步骤】

    • 判断栈是否满,若满则返回ERROR

    • 将新元素压入栈顶,栈顶指针增加1

      Status Push(SqStack &S, SElemType e)
      {//插入元素e为新的栈顶元素
          if(S.top-S.base==S.stacksize) return ERROR;//栈满
          *S.top++=e;//元素e压入栈顶,栈顶指针加1
          return OK;  
      }
      

      注:对指针*运算是对其所指空间进行操作。

  4. 顺序栈的出栈

    【算法步骤】

    • 判断栈是否空,若空则返回ERROR。

    • 栈顶指针减1,栈顶元素出栈。

      Status Pop(SqStack &S, SElemType e)
      {//删除S的栈顶元素,用e返回其值
          if(S.top==S.base) return ERROR;//栈空
          e=*--S.top;//栈顶指针减1,将栈顶元素赋给e
          return OK;
      }
      
  5. 取顺序栈的栈顶元素

    SElemType GetTop(SqStack S)
    {//返回S的栈顶元素,不修改栈顶指针
        if(S.top!=S.base)//栈非空
            return *(S.top-1);//返回栈顶元素的值,栈顶指针不变
    }
    

链栈

  1. 链栈的定义

    //------链栈的存储结构------
    typedef struct StackNode
    {
        ElemType data;
        struct StackNode *next;
    }StackNode,*LinkStack;
    

    注:由于栈的主要操作是在栈顶插入和删除,显然以链表的头部作为栈顶是最方便的。

  2. 链栈的初始化

    Status InitStack(LinkStack &S)
    {//构造一个空栈,栈顶指针置空
        S=NULL;
        return OK;
    }
    
  3. 链栈的入栈

    【算法步骤】

    • 为入栈元素e分配空间,用指针p指向。

    • 将新结点数据域置为e。

    • 将新结点插入栈顶。

    • 修改栈顶指针为p。

      Status Push(LinkStack &S, SElemType e)
      {//在栈顶插入元素e
          p=new StackNode;//生成新结点
          p->data=e;//将新结点数据域置为e
          p->next=S;//将新结点插入栈顶
          S=p;//修改栈顶指针为p
          return OK;
      }
      
  4. 链栈的出栈

    【算法步骤】

    • 判断栈是否为空,若空则返回ERROR。

    • 将栈顶元素赋给e。

    • 临时保存栈顶元素的空间,以备释放。

    • 修改栈顶指针,指向新的栈顶元素。

    • 释放原栈顶元素的空间。

      Status Pop(LinkStack &S,SElemType &e)
      {//删除S的栈顶元素,用e返回其值、
          if(S==NULL) return ERROR;//栈空
          e=S->data;//将栈顶元素赋给e
          p=S;//用p临时保存栈顶元素的空间,以备释放
          S=S->next;//修改栈顶指针
          delete p;//释放原栈顶元素的空间
          return OK;
      }
      
  5. 取链栈栈顶元素

    SElemType GetTop(LinkStack S)
    {//返回S的栈顶元素,不修改栈顶指针
        if(S!=NULL)//栈非空
            return S->data;
    }
    

你可能感兴趣的:(数据结构基础知识,概念,数据结构,笔记,经验分享,考研)