• 数据结构学习笔记(三:栈和队列)


    栈的基本概念

    1.栈的定义

    • 栈(Stack):只允许在一端进行插入或删除的线性表
    • 栈顶(Top):线性表允许进行插入和删除的那一端。
    • 栈底(Bottom):固定的,不允许进行插入和删除的另一端。
    • 空栈:不含任何元素的空表。
    • 栈的操作特性为后进先出(LIFO)
    • 栈的数学性质:n个不同元素进栈,出栈元素不同排列的个数为(frac{1}{n+1}C^n_{2n})

    2.栈的基本操作

    • InitStack(&S): 初始化一个空栈S。
    • StackEmpty(S): 判断一个栈是否为空。
    • Push(&S, x): 进栈,若S未满,则将x加入使之成为新栈顶。
    • Pop(&S, &x): 出栈,若S非空,则弹出栈顶元素,并用x返回。
    • GetTop(&S, &x): 读栈顶元素,若S非空,则用x返回栈顶元素。
    • DestoryStack(&S): 销毁栈,并释放S占用的存储空间。

    栈的顺序存储结构

    1.顺序栈

    • 顺序栈利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针(top)指示当前栈顶元素的位置。

    • 顺序栈的存储类型描述:

      #define MaxSize 50
      typedef struct {
          Elemtype data[MaxSize];
          int top;
      } SqStack;
      
    • 栈顶指针:S.top,初始时设置S.top=-1

    • 栈顶元素:S.data[S.top]

    • 进栈操作:栈未满时,栈顶指针先加1,再赋值给栈顶元素

      bool Push(SqStack &S, ElemType x) {
          if (S.top == MaxSize - 1)
              return false;
          S.data[++S.top] = x;
          return true;
      
    • 出栈操作:栈非空时,先取栈顶元素值,再将栈顶指针减1

    • 栈空条件:S.top==-1

    • 栈满条件:S.top==MaxSize-1

    • 栈长:S.top+1

    2.共享栈

    • 利用栈底位置相对不变的特性,可让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸。
    • top0=-1时,0号栈为空,top1=MaxSize时1号栈为空
    • 仅当两个栈顶指针相邻(top1-top0=1)时,判断为栈满。
    • 当0号栈进栈时top0先加1再赋值,1号栈进栈时top1先减1再赋值;出栈时则刚好相反。

    栈的链式存储

    • 链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。

    • 通常采用单链表实现,并规定所有操作都是在单链表的表头进行的。这里规定链栈没有头结点,头指针指向栈顶元素。

    • 链栈的类型描述:

      typedef struct Linknode {
          ELemType data;
          struct Linknode *next;
      } *LiStack;
      

    队列的基本概念

    1. 队列的定义

    • 队列也是一种操作受限的线性表,只允许在表的一端进行插入,而在表的另一端进行删除
    • 队列的操作特性是先进先出(FIFO)
    • 队头(Front):允许删除的一端,又称队首
    • 队尾(Rear):允许插入的一端
    • 空队列:不含任何元素的空表

    2. 队列常见的基本操作

    • InitQueue(&Q):
    • QueueEmpty(Q):
    • EnQueue(&Q, x):
    • DeQueue(&Q, &x):
    • GetHead(Q, &x):

    队列的顺序存储结构

    1. 顺序队列

    • 队列的顺序实现是指分配一块连续的存储单元存放队列中的元素,并附设两个指针:
      • 队头指针front指向队头元素
      • 队尾指针rear指向队尾元素的下一个位置
    • 顺序队列的类型描述:
      #define MaxSize 50
      typedef struct {
          ElemType data[MaxSize];
          int front, rear; 
      } SqQueue;
      
    • 初始状态(队空条件):Q.front == Q.rear == 0
    • 进队操作:队不满时,先送值到队尾元素,再将队尾指针加1
    • 出队操作:队不为空时,先取队头元素值,再将队头指针加1
    • d中仅有一个元素,此时入队出现“上溢出”,但这种一处并不是真正的溢出,在data数组中依然存在可以存放元素的空位,所以这是一种“假溢出”

    2.循环队列

    • 循环队列弥补了顺序队列“假溢出”的缺陷
    • 将顺序队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,成为循环队列
    • 当队首指针Q.front = MaxSize - 1后,在前进一个位置就自动到0,这可以利用取余运算(%)实现
      • 初始时:Q.front = Q.rear = 0
      • 队首指针进1:Q.front = (Q.front + 1) % MaxSize
      • 队尾指针进1:Q.rear = (Q.rear + 1) % MaxSize
      • 队列长度:(Q.rear + MaxSize - Q.front) % MaxSize
      • 出入队时:指针都按顺时针方向进1
      • 区分是队空还是队满
          1. 牺牲一个单元来区分,队头指针在队尾指针的下一位置作为队满标志,如图d2
          • 队满条件:(Q.rear + 1) % MaxSize == Q.front
          • 队空条件:Q.front == Q.rear
          • 队列中元素个数:(Q.rear - Q.front + MaxSize) % MaxSize
          1. 类型中增设表示元素个数的数据成员。
          • 队满条件:Q.size == MaxSize
          • 队空条件:Q.size == 0
          1. 类型中增设tag数据成员
          • 队满条件:tag == 1 && Q.front == Q.rear
          • 队空条件:tag == 0 && Q.front == Q.rear

    队列的链式存储结构

    1. 链队列

    • 实际上是一个同时带有队头指针和队尾指针的单链表

    • 头指针指向队头结点,尾指针指向队尾结点(与顺序队列不同)

    • 链队列的类型描述

      typedef struct {
          ElemType data;
          struct LinkNode *next
      } LinkNode;
      typedef struct {
          LinkNode *front, *rear
      } LinkQueue;
      
    • 队空条件:Q.front == NULL && Q.rear == NULL

    • 出队时,首先判断队列是否为空,若不为空,则取出队头元素,将其从链表中摘除,并让Q.front指向下一个结点(若该节点为最后一个结点,则置Q.front和Q.rear都为NULL)

    • 入队时,建立一个新结点,将新结点插入到链表的尾部,并让Q.rear指向这个新插入的结点(若原队列为空队,则令Q.front也指向该结点)

    • 通常将链队列设计成一个带头结点的单链表,统一插入和删除

    • 链队列适用于数据元素变动比较大的情形,而且不存在队满和溢出的问题

  • 相关阅读:
    大型网站技术架构-阅读笔记1
    如何发挥一个字节的极限,存储大量内容
    利用easyui创建一个简单的登录页面
    linux tomcat 快捷操作
    linux 安装jdk
    Linux-查看服务器的信息
    HTTP协议(1)
    Linux-ps命令
    Linux-tcpdump命令
    转载-测试新人培训方法之目标法
  • 原文地址:https://www.cnblogs.com/missionA/p/12659337.html
Copyright © 2020-2023  润新知