数据结构 | 栈与队列和数组

文章目录

    • 栈的基本概念
      • 栈的定义
      • 栈的基本操作
      • 栈的基本操作代码实现
      • 栈的常考题型
    • 栈的顺序存储实现
      • 顺序栈的定义
      • 初始化操作
      • 进栈操作
      • 出栈操作
      • 读栈顶元素操作
      • 另一种方式
      • 共享栈
    • 顺序栈存储实现代码实现
    • 栈的链式存储实现
      • 链栈的定义
      • 链栈的基本操作
    • 链栈的代码实现
    • 队列的基本概念
      • 队列的定义
      • 队列的基本操作
    • 队列的顺序实现
      • 定义
      • 初始化操作
      • 入队操作
      • 循环队列
        • 入队操作
        • 出队操作
      • 方案一:判断队列已满/已空(牺牲一片存储空间)
      • 方案二:判断队列已满/已空(size)
      • 方案三:判断队列已满/已空(tag)
      • 其他出题方法
    • 队列顺序实现代码实现
    • 队列的链式实现
      • 定义
      • 初始化(带头结点)
      • 初始化(不带头结点)
      • 入队(带头结点)
      • 入队(不带头结点)
      • 出队(带头结点)
      • 出队(不带头结点)
      • 队列满的条件
    • 队列链式实现代码实现
    • 双端队列
      • 定义
      • 考点:判断输出序列合法性
        • 输入受限的双端队列
        • 输出受限的双端队列
    • 栈在括号匹配中的应用
      • 括号匹配问题
      • 算法演示
      • 算法实现详细过程
      • 算法的代码实现
    • 栈在表达式求值中的应用
      • 大家熟悉的算术表达式
      • 波兰数学家的灵感
      • 中缀、后缀、前缀表达式
      • 中缀表达式转后缀表达式(手算)
      • 后缀表达式的计算(手算)
      • 后缀表达式的计算(机算)
      • 中缀表达式转前缀表达式(手算)
      • 前缀表达式的计算
      • 中缀表达式转后缀表达式(机算)
        • 不带界限符(括号)的例子
        • 带有界限符(括号)的例子
      • 中缀表达式的计算(用栈实现)
        • 实现原理
        • 具体实现过程
    • 栈在递归中的应用
      • 函数调用背后的过程
      • 栈在递归当中的应用
    • 队列的应用
      • 树的层次遍历
      • 图的广度优先遍历
      • 队列在操作系统中的应用
    • 特殊矩阵的压缩存储
      • 一维数组的存储结构
      • 二维数组的存储结构
      • 普通矩阵的存储
      • 对称矩阵的压缩存储
      • 三角矩阵的压缩存储
      • 三对角矩阵的压缩存储
      • 稀疏矩阵的压缩存储

栈的基本概念

数据结构 | 栈与队列和数组_第1张图片

栈的定义

数据结构 | 栈与队列和数组_第2张图片
数据结构 | 栈与队列和数组_第3张图片

栈的基本操作

数据结构 | 栈与队列和数组_第4张图片

栈的基本操作代码实现

//栈的基本操作

//初始化一个栈
InitStack(&S)

//销毁栈
DestroyStack(&S)

//进栈
Push(&S,x)

//出栈
Pop(&S,&x)

//读取栈顶元素
GetTop(S,&x)

//判断栈是否为空
StackEmpty(S)

栈的常考题型

数据结构 | 栈与队列和数组_第5张图片
数据结构 | 栈与队列和数组_第6张图片

栈的顺序存储实现

数据结构 | 栈与队列和数组_第7张图片

顺序栈的定义

数据结构 | 栈与队列和数组_第8张图片

初始化操作

数据结构 | 栈与队列和数组_第9张图片

进栈操作

数据结构 | 栈与队列和数组_第10张图片
数据结构 | 栈与队列和数组_第11张图片

出栈操作

数据结构 | 栈与队列和数组_第12张图片

读栈顶元素操作

数据结构 | 栈与队列和数组_第13张图片

另一种方式

数据结构 | 栈与队列和数组_第14张图片
数据结构 | 栈与队列和数组_第15张图片

共享栈

数据结构 | 栈与队列和数组_第16张图片
数据结构 | 栈与队列和数组_第17张图片

顺序栈存储实现代码实现

#include

//顺序栈的定义
#define MaxSize 10 //定义栈中元素的最大个数
typedef struct{
  int data[MaxSize]; //静态数组存放栈中元素
  int top; //栈顶指针
}SqStack;

//顺序栈的初始化
void InitStack(SqStack &S){
  S.top = -1; //初始化栈顶指针
}

//判断顺序栈是否为空
bool StackEmpty(SqStack S){
  if(S.top == -1){ //栈空
    return true;
  }else{ //栈不空
    return false;
  }
}

//新元素入栈
bool Push(SqStack &S,int x){
  if(S.top == MaxSize-1){ //栈满,报错
    return false;
  }
  S.data[++S.top] = x; //指针加1,新元素入栈
  return true;
}

//出栈操作
bool Pop(SqStack &S,int &x){
  if(S.top == -1){ //栈空,报错
    return false;
  }
  x = S.data[S.top--]; //栈顶元素出栈,指针减1
  return true;
}

//读取栈顶元素
bool GetTop(SqStack S,int &x){
  if(S.top == -1){ //栈空,报错
    return false;
  }
  x = S.data[S.top]; //x记录栈顶元素
  return true;
}

//共享栈的定义
#define MaxSize 10 //定义栈中元素的最大个数
typedef struct{
  int data[MaxSize]; //静态数组存放栈中元素
  int top0; //0号栈栈顶指针
  int top1; //1号栈栈顶指针
}ShStack;

//共享栈的初始化操作
void InitStack(ShStack &S){
  S.top0 = -1; //初始化0号栈栈顶指针
  S.top1 = MaxSize; //初始化1号栈栈顶指针
}

//共享栈判断栈满
bool FullStack(ShStack S){
  return S.top0 + 1 == S.top1;
}

栈的链式存储实现

数据结构 | 栈与队列和数组_第18张图片

链栈的定义

数据结构 | 栈与队列和数组_第19张图片

链栈的基本操作

  • 用链式存储实现的栈它的本质上也是一个单链表
  • 只不过我们规定我们只能在头结点这一端进行插入和删除操作
  • 也就是把链头的这一段看成是我们栈顶的这一端
  • 所以链栈的定义和单链表的定义几乎没有区别,只是把名字稍微改了下而已
    数据结构 | 栈与队列和数组_第20张图片
    数据结构 | 栈与队列和数组_第21张图片

数据结构 | 栈与队列和数组_第22张图片

链栈的代码实现

#include

//链栈的定义
typedef struct LinkNode{
  int data; //数据域
  struct LinkNode *next; //指针域
}*LinkStack; //栈类型定义

//链栈的初始化
bool InitStack(LinkStack *L){
  L->next = NULL;
  return true;
}

//链栈进栈操作
bool Push(LinkStack &L,int e){
  if(L == NULL){
    return false;
  }
  LinkStack *s = (LinkStack *)malloc(sizeof(LinkStack));
  if(s == NULL){
    return false;
  }
  s->data = e;
  s->next = L->next;
  L = s;
  return true;
}

//链栈的出栈操作
bool Pop(LinkStack &L,int &e){
  if(L == NULL){
    return false;
  }
  LinkStack *q = L;
  e = q->data;
  L = q->next;
  free(q);
  return true;
}

//链栈获取栈顶元素
bool GetTop(LinkStack L,int &x){
  if(L == NULL){
    return false;
  }
  x = L->data;
  return true;
}

//链栈如何判空/判满
bool IsEmpty(LinkStack L){
  if(L == NULL){
    return true;
  }else{
    return false;
  }
}

队列的基本概念

数据结构 | 栈与队列和数组_第23张图片

队列的定义

数据结构 | 栈与队列和数组_第24张图片
数据结构 | 栈与队列和数组_第25张图片
数据结构 | 栈与队列和数组_第26张图片

队列的基本操作

数据结构 | 栈与队列和数组_第27张图片

//队列的基本操作

//初始化队列
InitQueue(&Q)

//销毁队列
DestroyQueue(&Q)

//入队
EnQueue(&Q,x)

//出队
DeQueue(&Q,&x)

//获取队头元素
GetHead(&Q,&x)

//判断队列是否为空
IsQueueEmpty(Q)

数据结构 | 栈与队列和数组_第28张图片

队列的顺序实现

数据结构 | 栈与队列和数组_第29张图片

定义

数据结构 | 栈与队列和数组_第30张图片

初始化操作

数据结构 | 栈与队列和数组_第31张图片

入队操作

数据结构 | 栈与队列和数组_第32张图片

循环队列

数据结构 | 栈与队列和数组_第33张图片

  • rear指针指向下一个可以插入数据的位置的循环队列中队列满的条件为什么会空一块出来?
  • 我们是通过front指针和rear指针是否指向同一个位置来判断队列是否为空,如果不留一个空则无法判断队列此时是满还是为空,只能牺牲掉一个数据单元
入队操作

数据结构 | 栈与队列和数组_第34张图片

出队操作

数据结构 | 栈与队列和数组_第35张图片

方案一:判断队列已满/已空(牺牲一片存储空间)

数据结构 | 栈与队列和数组_第36张图片

方案二:判断队列已满/已空(size)

数据结构 | 栈与队列和数组_第37张图片

方案三:判断队列已满/已空(tag)

  • tag == 0 表示最近执行的是一次删除操作
  • tag == 1 表示最近执行的是一次插入操作
    数据结构 | 栈与队列和数组_第38张图片

其他出题方法

数据结构 | 栈与队列和数组_第39张图片
数据结构 | 栈与队列和数组_第40张图片
数据结构 | 栈与队列和数组_第41张图片
数据结构 | 栈与队列和数组_第42张图片

队列顺序实现代码实现

#include

//顺序链表的定义
#define MaxSize 10 //定义队列中元素的最大个数
typedef struct{
  int data[MaxSize]; //用静态数组存放队列元素
  int front,rear; //队头指针和队尾指针
}SqQueue;

//顺序队列的初始化操作
void InitQueue(SqQueue &Q){
  //初始化时,队头和队尾指针指向0
  Q.front = 0;
  Q.rear = 0;
}

//入队操作
bool EnQueue(SqQueue &Q,int x){
  if((Q.rear + 1) % MaxSize == Q.front){ //队列满则报错
    return false;
  }
  Q.data[Q.rear] = x;
  Q.rear = (Q.rear + 1) % MaxSize;
  return true;
}

//出队操作
bool DeQueue(SqQueue &Q,int &x){
  if(Q.rear == Q.front){ //队空则报错
    return false;
  }
  x = Q.data[Q.front];
  Q.front = (Q.front + 1) % MaxSize;
  return true;
}

//获取队头元素的值并用x值返回
bool GetHead(SqQueue &Q,int &x){
  if(Q.rear == Q.front){
    return false;
  }
  x = Q.data[Q.front];
  return true;
}

//判断队列是否为空
bool IsQueueEmpty(SqQueue Q){
  if(Q.rear == Q.front){
    return true;
  }else{
    return false;
  }
}

队列的链式实现

数据结构 | 栈与队列和数组_第43张图片

定义

数据结构 | 栈与队列和数组_第44张图片

初始化(带头结点)

数据结构 | 栈与队列和数组_第45张图片

初始化(不带头结点)

数据结构 | 栈与队列和数组_第46张图片

入队(带头结点)

数据结构 | 栈与队列和数组_第47张图片

入队(不带头结点)

数据结构 | 栈与队列和数组_第48张图片

出队(带头结点)

数据结构 | 栈与队列和数组_第49张图片

出队(不带头结点)

数据结构 | 栈与队列和数组_第50张图片

队列满的条件

数据结构 | 栈与队列和数组_第51张图片

数据结构 | 栈与队列和数组_第52张图片

队列链式实现代码实现

#include

//链队列的定义
typedef struct LinkNode{
  int data;
  struct LinkNode *next;
}LinkNode;

typedef struct{
  LinkNode *front,*rear;
}LinkQueue;

//初始化(带头结点)
void InitQueue(LinkQueue &Q){
  //初始化时,front和rear指针都指向头结点
  LinkQueue *s = (LinkNode *)malloc(sizeof(LinkNode));
  Q.front = s;
  Q.rear = s;
}

//判断队列是否为空(带头结点)
bool IsQueueEmpty(LinkQueue Q){
  if(Q.front == Q.rear){
    return true;
  }else{
    return false;
  }
}

//初始化(不带头结点)
void InitQueue(LinkQueue &Q){
  Q.front = NULL;
  Q.rear = NULL;
}

//判断队列是否为空(不带头结点)
bool IsQueueEmpty(LinkQueue Q){
  if(Q.front == NULL){
    return true;
  }else{
    return false;
  }
}

//入队(带头结点)
void EnQueue(LinkQueue &Q,int x){
  LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
  s->data = x;
  s->next = NULL;
  Q.rear->next = s; //新结点插入到rear之后
  Q.rear = s; //修改表尾指针
}

//入队(不带头结点)
void EnQueue(LinkQueue &Q,int x){
  LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
  s->data = x;
  s->next = NULL;
  if(Q.front == NULL){
    Q.front = s;
    Q.rear = s;
  }else{
    Q.rear->next = s; //新结点插入到rear之后
    Q.rear = s; //修改表尾指针
  }
}

//出队(带头结点)
bool DeQueue(LinkQueue &Q,int &x){
  if(Q.front == Q.rear){
    return false;
  }
  LinkNode *p = Q.front->next;
  x = p->data;
  Q.front->next = p->next;
  if(Q.rear == p){
    Q.rear == Q.front;
  }
  free(q);
  return false;
}

//入队(不带头结点)
bool DeQueue(LinkQueue &Q,int &x){
  if(Q.front == NULL){
    return false;
  }
  LinkNode *p = Q.front;
  x = p->data;
  Q.front = p->next;
  if(Q.rear == p){
    Q.front == NULL;
    Q.rear == NULL;
  }
  free(q);
  return false;
}

双端队列

定义

数据结构 | 栈与队列和数组_第53张图片
数据结构 | 栈与队列和数组_第54张图片

考点:判断输出序列合法性

数据结构 | 栈与队列和数组_第55张图片

输入受限的双端队列
  • 栈中合法的序列,在双端队列中也一定合法
  • 由于只能在一端进行输入,所以在序号较大的元素出队之前,其他的序号较小的元素已经可以确定它们在队列里面的相对位置
  • 绿色的和有下划线的都是合法的,红色的无下划线的是非法的
    数据结构 | 栈与队列和数组_第56张图片
输出受限的双端队列
  • 栈中合法的序列,双端队列中也一定合法
  • 我们在对这些序列进行验证的时候,很重要的一点就是如果你在输出序列当中看到了某一个序号的元素,那么在这个元素输出之前意味着它之前的所有元素肯定都已经输入到这个队列里面了
    数据结构 | 栈与队列和数组_第57张图片
    数据结构 | 栈与队列和数组_第58张图片

栈在括号匹配中的应用

括号匹配问题

数据结构 | 栈与队列和数组_第59张图片
数据结构 | 栈与队列和数组_第60张图片

算法演示

  • 遇到左括号就入栈

  • 遇到右括号,就“消耗”一个左括号

  • case_1:

数据结构 | 栈与队列和数组_第61张图片

  1. 前面3个括号都是左括号,分别压入栈中
  2. 遇到了一个右括号③,栈顶弹出一个左括号③和其匹配
  3. 遇到了一个右括号②,栈顶弹出一个左括号②和其匹配

数据结构 | 栈与队列和数组_第62张图片

  1. 遇到了一个左括号④,压入栈中
  2. 遇到了一个右括号④,栈顶弹出一个左括号④和其匹配
  3. 遇到了一个右括号①,栈顶弹出一个左括号①和其匹配
    在这里插入图片描述
  • case_2:
  1. 前面都是左括号,分别压入栈中
    数据结构 | 栈与队列和数组_第63张图片
  2. 遇到了一个右括号③,栈顶弹出一个左括号③和其匹配
  3. 遇到了一个右括号②,栈顶弹出一个左括号②和其匹配
    数据结构 | 栈与队列和数组_第64张图片
  4. ②括号匹配失败,本次括号匹配结束
    数据结构 | 栈与队列和数组_第65张图片
  • case_3:
    数据结构 | 栈与队列和数组_第66张图片
  • case_4:
    数据结构 | 栈与队列和数组_第67张图片

算法实现详细过程

数据结构 | 栈与队列和数组_第68张图片

算法的代码实现

数据结构 | 栈与队列和数组_第69张图片
数据结构 | 栈与队列和数组_第70张图片

栈在表达式求值中的应用

数据结构 | 栈与队列和数组_第71张图片

大家熟悉的算术表达式

数据结构 | 栈与队列和数组_第72张图片

波兰数学家的灵感

数据结构 | 栈与队列和数组_第73张图片

中缀、后缀、前缀表达式

数据结构 | 栈与队列和数组_第74张图片

中缀表达式转后缀表达式(手算)

数据结构 | 栈与队列和数组_第75张图片
数据结构 | 栈与队列和数组_第76张图片
数据结构 | 栈与队列和数组_第77张图片

后缀表达式的计算(手算)

数据结构 | 栈与队列和数组_第78张图片

数据结构 | 栈与队列和数组_第79张图片
数据结构 | 栈与队列和数组_第80张图片

后缀表达式的计算(机算)

在这里插入图片描述

  • 扫描到A、B两个操作数,直接压入栈中
    数据结构 | 栈与队列和数组_第81张图片
  • 扫描到的是+操作符,依次弹出两次栈顶元素B、A,执行A+B(注意这里先弹出的是后操作数,后弹出的是前操作数)
    数据结构 | 栈与队列和数组_第82张图片
    数据结构 | 栈与队列和数组_第83张图片
    数据结构 | 栈与队列和数组_第84张图片

数据结构 | 栈与队列和数组_第85张图片
数据结构 | 栈与队列和数组_第86张图片
数据结构 | 栈与队列和数组_第87张图片
数据结构 | 栈与队列和数组_第88张图片

  • 类似的,这种算法思想不仅仅可以求值,而且还可以实现后缀表达式转化为带括号的中缀表达式

中缀表达式转前缀表达式(手算)

数据结构 | 栈与队列和数组_第89张图片
数据结构 | 栈与队列和数组_第90张图片

前缀表达式的计算

数据结构 | 栈与队列和数组_第91张图片

数据结构 | 栈与队列和数组_第92张图片

数据结构 | 栈与队列和数组_第93张图片

中缀表达式转后缀表达式(机算)

数据结构 | 栈与队列和数组_第94张图片

不带界限符(括号)的例子
  • 依次扫描,遇到操作数A直接加入后缀表达式
    数据结构 | 栈与队列和数组_第95张图片

  • 往下扫描,遇到操作符+,由于此时栈内为空,直接把操作符压入栈内
    在这里插入图片描述

  • 往下扫描,遇到操作数B直接加入后缀表达式
    数据结构 | 栈与队列和数组_第96张图片

  • 往下扫描,遇到操作符-,由于此时-的优先级和+是同一个优先级的,所以我们要先把栈里面的+弹出栈(这里这样操作的依据是在+后面扫面到了一个-。这就说明+-中间肯定是加进去了一个操作数,扫到-就说明中间加入的这个数肯定要进行加法运算也要进行减法运算,而由于这两个运算的优先级是相等的,根据上面“左优先”的原则,我们要先执行左边的运算符所代表的运算,后缀表达式中各运算符出现的先后顺序就是它们生效的顺序)
    数据结构 | 栈与队列和数组_第97张图片

  • 然后把A+B看作一个整体继续往后扫描,C是一个操作数可以直接输出
    数据结构 | 栈与队列和数组_第98张图片

  • 再往后是一个操作符 *,经过检查发现此时栈顶的元素是一个-,这意味着我们扫描到的C这个操作数前面是个减法运算,后面是个乘法运算,根据先乘除后加减,所以就不能先把-给弹出栈,但是我们也不能直接把*直接加入表达式让乘法先运行,因为我们不确定后面会不会出现括号,所以我们这里先将*给压入栈中
    数据结构 | 栈与队列和数组_第99张图片

  • 再往后扫描是一个操作数D,直接加入表达式中
    数据结构 | 栈与队列和数组_第100张图片

  • 往下扫描,扫描到了一个操作符/,意味着这个/左边的操作数D既要进行乘法操作也要进行除法操作,由于除法和乘法它们的优先级是相等的,所以我们可以让左边的乘法先生效,先把这个*给弹出栈,这个时候我们需要把CD*AB+都看成一个整体

  • 此时栈顶元素是-,意味着此时/左边的操作数CD*既要进行减法也要进行除法操作,虽然除法此时的优先级是比减法要高的,但是我们此时不能确定/后面会不会跟着类似于(E+F)这样的小括号,所以我们此时也不能确定此时可不可以让除法先生效,所以此时还是需要把/给压入栈里面
    数据结构 | 栈与队列和数组_第101张图片

  • 继续往后是一个操作数E,可以直接输出
    数据结构 | 栈与队列和数组_第102张图片

  • 再往后是一个操作符+,由于此时的栈顶元素是一个/,意味着+左边的操作数既需要除法也需要加法,没有括号,此时我们就可以确定应该让除法先生效,我们就可以大胆地把优先级更高的/给弹出栈中,此时意味着我们需要把CD*E/看作一个整体
    数据结构 | 栈与队列和数组_第103张图片

  • 此时的栈顶元素是-,意味着+中间的这个操作数既要减法也要加法,根据优先级以及左优先,我们让-弹出栈,加入表达式当中
    数据结构 | 栈与队列和数组_第104张图片

  • 再往后是一个操作数F,直接加入表达式,此时的字符都处理完了,我们把栈里的运算符依次弹出加入表达式
    数据结构 | 栈与队列和数组_第105张图片

带有界限符(括号)的例子

数据结构 | 栈与队列和数组_第106张图片

数据结构 | 栈与队列和数组_第107张图片

数据结构 | 栈与队列和数组_第108张图片
数据结构 | 栈与队列和数组_第109张图片

数据结构 | 栈与队列和数组_第110张图片

  • 接下来扫到的是一个界限符(,如果遇到(我们要把它直接入栈,但是(是不加入后缀表达式的
    数据结构 | 栈与队列和数组_第111张图片
    数据结构 | 栈与队列和数组_第112张图片
  • 此时扫描到的是一个-,按照规则我们需要弹出栈顶所有优先级高于或者等于-的运算符(遇到左括号(或者栈空则停止)
  • 当前栈中(上面没有任何操作符,所以我们直接把-压进栈中
  • 背后的逻辑是扫描到-的时候,-左边的操作数的左边有一个左括号,显然我们需要优先计算括号里面的内容,但是我们不能确定-后面的操作数后面会不会跟有一个乘法或者除法操作,所以我们不能确定这个减法是否可以立即生效,所以需要把-压入栈中
    数据结构 | 栈与队列和数组_第113张图片
    数据结构 | 栈与队列和数组_第114张图片
  • 当我们遇到右括号)的时候,我们需要依次弹出栈内的运算符并加入后缀表达式,知道弹出左括号(为止,但是注意左括号(不能加入后缀表达式
  • 所以我们这里弹出-,加入后缀表达式,再弹出左括号(,舍弃
  • 背后的逻辑是,扫到右括号)的时候我们已经可以知道括号的作用范围了,我们必须优先计算括号内的内容,所以括号里面的所有内容都可以先生效,所以我们可以大胆地弹出括号里面的内容
    数据结构 | 栈与队列和数组_第115张图片
    数据结构 | 栈与队列和数组_第116张图片
    数据结构 | 栈与队列和数组_第117张图片
    数据结构 | 栈与队列和数组_第118张图片
    数据结构 | 栈与队列和数组_第119张图片
    数据结构 | 栈与队列和数组_第120张图片
  • 可以利用下面的表达式自己模拟一下过程:
    数据结构 | 栈与队列和数组_第121张图片

中缀表达式的计算(用栈实现)

实现原理

数据结构 | 栈与队列和数组_第122张图片
数据结构 | 栈与队列和数组_第123张图片
数据结构 | 栈与队列和数组_第124张图片

具体实现过程

数据结构 | 栈与队列和数组_第125张图片

  • 扫到A,直接放入操作数栈里面
    数据结构 | 栈与队列和数组_第126张图片
  • 扫到+,按照“中缀转后缀”的逻辑,此时栈是空的,直接把+压入栈中
    数据结构 | 栈与队列和数组_第127张图片
  • 扫描到操作数B,把它压进操作数栈里面
    数据结构 | 栈与队列和数组_第128张图片
  • 扫描到一个-,按照“中缀转后缀”的逻辑,我们已经可以确定栈顶的+已经可以生效了,所以我们需要将运算符栈里面的栈顶元素+弹出栈
  • 运算符+弹出后,我们需要在操作数栈里弹出两个栈顶元素AB并执行运算A+B后再压回操作数栈里
  • 再把当前扫描到的-给压入栈里
    数据结构 | 栈与队列和数组_第129张图片
  • 扫描到的是操作数C,直接入栈
    数据结构 | 栈与队列和数组_第130张图片
  • 扫描到的是**的优先级比-高,所以我们不需要把-弹出,直接把*压入运算符栈中
    数据结构 | 栈与队列和数组_第131张图片
  • 接下来遇到一个操作数D,入栈
    数据结构 | 栈与队列和数组_第132张图片
  • 扫描到一个/,根据”中缀转后缀“的逻辑,我们需要把*弹出栈,此时*运算符生效,我们需要在操作数栈中弹出两个栈顶元素CD并进行计算C*D再把结果压回操作数栈
    数据结构 | 栈与队列和数组_第133张图片
  • 扫描到的是操作数E,直接入栈
    数据结构 | 栈与队列和数组_第134张图片
  • 扫描到的是+,根据”中缀转后缀“的逻辑,此时/运算符生效,我们需要在操作数栈中弹出两个栈顶元素EC*D并进行计算(C*D)/E再把结果压回操作数栈
  • 根据”中缀转后缀“的逻辑,此时-运算符生效,我们需要在操作数栈中弹出两个栈顶元素A+B(C*D)/E并进行计算(A+B)-(C*D)/E再把结果压回操作数栈
  • 再把当前扫描到的运算符+压到运算符栈里面
    数据结构 | 栈与队列和数组_第135张图片
  • 之后扫描到的是操作数F,直接把它压入栈里
    数据结构 | 栈与队列和数组_第136张图片
  • 当我们扫描完所有的东西之后,按照”中缀转后缀“的逻辑,我们需要把运算符栈里面的所有运算符都依次地弹出栈
  • 每当弹出一个运算符的时候就需要让一个运算符生效,由于此时运算符栈里面只剩下+,则让+生效,根据”中缀转后缀“的逻辑,我们需要在操作数栈中弹出两个栈顶元素F(A+B)-(C*D)/E并进行计算(A+B)-(C*D)/E+F再把结果压回操作数栈
  • 最后留在操作数栈里面的内容就是我们所求的表达式的值
    数据结构 | 栈与队列和数组_第137张图片
    数据结构 | 栈与队列和数组_第138张图片

栈在递归中的应用

函数调用背后的过程

数据结构 | 栈与队列和数组_第139张图片

栈在递归当中的应用

数据结构 | 栈与队列和数组_第140张图片
在这里插入图片描述
数据结构 | 栈与队列和数组_第141张图片
数据结构 | 栈与队列和数组_第142张图片
数据结构 | 栈与队列和数组_第143张图片

队列的应用

树的层次遍历

  • 在访问一个结点的时候要分别把其左右孩子依次放到队列的队尾
  • 遍历完的结点可以出队并删除
    数据结构 | 栈与队列和数组_第144张图片

图的广度优先遍历

  • 新建一个队列
  • 当我们遍历一个结点的时候,就需要检查和这个结点相邻的其他结点有没有被遍历过,没有被遍历过的要一次放到队列的队尾
  • 访问处理完的结点就可以让其出队
    数据结构 | 栈与队列和数组_第145张图片

队列在操作系统中的应用

数据结构 | 栈与队列和数组_第146张图片
数据结构 | 栈与队列和数组_第147张图片

特殊矩阵的压缩存储

数据结构 | 栈与队列和数组_第148张图片

一维数组的存储结构

数据结构 | 栈与队列和数组_第149张图片

二维数组的存储结构

数据结构 | 栈与队列和数组_第150张图片
数据结构 | 栈与队列和数组_第151张图片
数据结构 | 栈与队列和数组_第152张图片

普通矩阵的存储

数据结构 | 栈与队列和数组_第153张图片

对称矩阵的压缩存储

数据结构 | 栈与队列和数组_第154张图片
数据结构 | 栈与队列和数组_第155张图片
数据结构 | 栈与队列和数组_第156张图片
数据结构 | 栈与队列和数组_第157张图片
数据结构 | 栈与队列和数组_第158张图片
数据结构 | 栈与队列和数组_第159张图片

三角矩阵的压缩存储

数据结构 | 栈与队列和数组_第160张图片
数据结构 | 栈与队列和数组_第161张图片
数据结构 | 栈与队列和数组_第162张图片

三对角矩阵的压缩存储

  • 三对角矩阵,又称为带状矩阵

数据结构 | 栈与队列和数组_第163张图片
数据结构 | 栈与队列和数组_第164张图片
数据结构 | 栈与队列和数组_第165张图片
数据结构 | 栈与队列和数组_第166张图片

稀疏矩阵的压缩存储

数据结构 | 栈与队列和数组_第167张图片
数据结构 | 栈与队列和数组_第168张图片
数据结构 | 栈与队列和数组_第169张图片
数据结构 | 栈与队列和数组_第170张图片

你可能感兴趣的:(计算机学科专业基础综合408,数据结构,数据结构,算法)