当前位置: 首页 > news >正文

NO.3数据结构栈和队列|顺序栈|共享栈|链栈|顺序队|循环队列|链队|双端队列|括号匹配|中缀表达式转后缀|后缀表达式求值

![[Pasted image 20250712091028.png]]

定义

![[Pasted image 20250712091322.png]]

只允许在一端进行插入 or 删除操作的线性表。
栈顶(top) : 允许进行插入删除操作的一端。
栈底(bottom) : 固定不变, 不允许进行任何操作。
栈可以为空。
![[Pasted image 20250712091347.png]]

卡特兰(Catalan) 函数

n 个不同元素进栈, 出栈元素不同的排列顺序的个数为:1n+1C2nn\frac{1}{n+1}C_{2n}^{n}n+11C2nn
当n个元素以某种顺序入栈,并且可以在任意时刻出栈,可以得到的元素排列数目满足卡特兰函数

顺序栈

——采用顺序存储的栈, 利用一组连续地址的存储单元存放
![[Pasted image 20250712091359.png]]

数据结构:
typedef struct Stack{  
Elemtype data[maxSize];  
int top;  
}SqStack;  
基本操作:

初始化:
![[Pasted image 20250712091629.png]]

SqStack S;  
S.top=-1;  

入栈(先判满) :
![[Pasted image 20250712091709.png]]

if(S.top != maxSize-1){  S.data[+ + S.top] = x;  
}else{  printf(“栈满”);  
}  

出栈(先判空) :
![[Pasted image 20250712091733.png]]

if(S.top != -1){  x = S.data[S.top - -];  
}else{  printf(“栈空”);  
}

注意: 当 top 初始值为-1 时, 进栈时先移动指针, 出栈时后移动指针! 初始为 0 则反之~

共享栈:

两个顺序栈共享同一个一维数组, 两个栈底分别位于共享数组的两端。
![[Pasted image 20250712092134.png]]

S0.top = -1 //initial
S0.data[++S0.top] = x; //push
x = S0.data[S0.top++]; //popS1.top = -1 //initial
S1.data[--S0.top] = x; //push
x = S1.data[S0.top++]; //popS0.top+1 == S1.top //OOM
S1.top-1 == S0.top //OOM

优点: 更有效地利用储存空间。

链栈

——采用链式存储方式的栈。 栈顶在队头, 栈底在队尾, 采用头插法入栈。
![[Pasted image 20250712092308.png]]

数据结构:
typedef struct LNode{  int data; //数据域  struct LNode *next; //指针
};
基本操作:

没有头节点的链栈入栈
![[Pasted image 20250712093450.png]]

S->next = top;
top = S;

没有头节点的链栈出栈
![[Pasted image 20250712100708.png]]

x = top;
top = top->next;
free(x);

一直出栈,需要判空

LinkNode *p = top;
if (top == NULL){printf("栈已空");
}
top = top->next;
free(p);

有头节点的入栈
![[Pasted image 20250712101109.png]]

S->next = top->next;
top->next = S;

![[Pasted image 20250712101405.png]]

队列

定义

只允许在一端插入, 另一端删除的线性表。
队头(front) : 允许删除的一端。
队尾(rear) : 允许插入的一端。
队列可以为空。

顺序队

——利用一块连续的存储单元进行存放。
![[Pasted image 20250712102214.png]]

数据结构:
typedef struct{  Elemtype data[MaxSize];  int front, rear; //队头指针, 队尾指针  
}SqQueue;
基本操作:

初始化:

SqQueue Q;
Q.rear = 0;  
Q.front = 0;  

入队(先判满):
![[Pasted image 20250712102406.png]]

if(队不满){  Q.data[Q.rear++] = x;  
}else{  print(“队满”)  
} 

出队(先判空):
![[Pasted image 20250712102416.png]]

if(队不空){  x = Q.data[Q.front++];  
}else{  print(“队空”)  
}

上溢
![[Pasted image 20250712102435.png]]

假溢出
![[Pasted image 20250712102449.png]]

循环队列:

由于普通队列存在“假溢出” , 故引入循环队列:
![[Pasted image 20250712102520.png]]

初始:

Q.rear = Q.front = 0;

入队:

Qu.data[Qu.rear] = x; 
Qu.rear = (Qu.rear + 1) % maxSize;  

出队:

x = Qu.data[Qu.front]; 
Qu.front = (Qu.front + 1) % maxSize;  

队列长度

(Q.rear + Q.MaxSize - Q.front) % MaxSize;
区分队空/满
  1. 牺牲一个空间
    队空:Q.rear = Q.front;
    队满:(Q.rear + 1) % MaxSize == Q.front;
  2. 加一个成员变量size,记录当前队列的元素规模
    入队:Q.size + 1;
    出队:Q.size - 1;
  3. 增设结构成员tag
    队空:Q.rear = Q.front, tag = 0;
    队满:Q.rear = Q.front, tag = 1;
    入队:Q.tag = 1;
    出队:Q.tag = 0;

链队

——利用链式结构进行存储, 实际上就是同时带有队头和队尾指针的单链表。
![[Pasted image 20250712103015.png]]

数据结构:
typedef struct{  Elemtype data;  struct LinkNode *next;  
}LinkNode;//链队结点  
typedef struct{  LinkNode *front, *rear;  
}LinkQueue;//链队  
基本操作

队空:Q.front == null, Q.rear == null;
入队:

Q.rear->next = s;  
Q.rear = s;  

没有头节点的链式队列入队

// 非空队列:
LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
Q.rear->next = s;
Q.rear = s;// 空队列:
if (Q,rear == NULL){Q.rear = s;Q.front = s;
}

有头节点的链式队列入队

// 非空队列:
LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
Q.rear->next = s;
Q.rear = s;// 空队列:
if (Q,rear == Q.front){Q.rear->next = s;Q.front = s;
}

出队:

x = Q.front->data;  
if(Q.front->next == null){ //被删除结点是不是队列最后一个元素  Q.front = null;  Q.rear = null;  
}else{  Q.front = Q.front->next;  
}

没有头节点的链式队列出队

if (Q.front != NULL){ //队不为空LinkNode *p = Q.front;if (Q.front->next == NULL){ //被删除节点是队列最后一个元素Q.front = NULL;Q.rear = NULL;}else{Q.front = Q.front->next;}free(p);
}

有头节点的链式队列出队

if (Q.front->next != NULL){ //队不为空LinkNode *p = Q.front->next;Q.front->next = p->next;if (Q.rear == p){ //被删除节点是队列最后一个元素Q.rear = Q.front;}free(p);
}

循环队列的提出是为了解决假溢出问题, 但是只能采取顺序存储的方式, 而链式队列不存在假溢出问题。 没有链式存储的循环队列。

使用链式队列的好处

  1. 内存动态分配
  2. 不存在假溢出的现象
  3. 适合多个队列的需求

双端队列

两端都可以进行入队和出队操作的队列。
![[Pasted image 20250712103401.png]]

输出受限双端队列: 两端都可入队, 但只能在一端进行出队。
![[Pasted image 20250712103412.png]]

输入受限双端队列: 两端都可出队, 但只能在一端进行入队。
![[Pasted image 20250712103424.png]]

应用

括号匹配

思路:

  1. 需要一个暂存括号的栈op
  2. 当遇到左括号时,入栈。
  3. 当遇到右括号时,将栈顶元素出栈,出栈元素应与当前右括号匹配,否则就是非法表达式;若当前栈顶为空,则也是非法表达式。
  4. 当遍历完成,若op栈不为空则表达式不合法,否则为合法表达式。
中缀表达式转换为后缀表达式

如何将a*(b+c)转换为逆波兰表达式?
思路:

  1. 需要两个栈,结果栈result 临时栈temp
  2. 遇到操作数时,直接将数字入栈result;
  3. 遇到操作符时
    a)若是’(‘,则直接入temp栈
    b)若是’)‘,说明temp中一定有’(‘与之对应,则将temp栈中的所有运算符依次出栈并入栈result,直到遇见’(',括号不会入result栈.
    c)若是+-*/运算符,则看当前的操作符与temp栈顶的运算符优先级,如果栈顶的运算符优先级更高,则将栈顶的运算符出栈并入栈result,否则当前操作符入栈temp。
  4. 当中缀表达式遍历完成后,将temp中的操作符依次出栈并入栈result, result栈中从栈底到栈顶的内容就是后缀表达式。
后缀表达式求值

【例题】计算后缀表达式23+1-2384/-的值
思路:

  1. 需要一个存储操作数的栈op
  2. 当遍历到操作数时,将操作数直接入op
  3. 当遍历到操作符时,将bp连续出栈两个操作数a,b,将运算 b op a的结果入栈op.
  4. 当遍历完成时,op栈底即为结果,
后缀表达式求值

【例题】利用栈直接计算表达式(2+3-1)2-3(8/4)的值思路:
将前面两个方法结合起来,中缀转后缀的过程中,每有一个op从temp栈中弹出时,都从result栈中弹出两个操作数a和b,计算b op a的结果再入栈result,最终遍历结束时result栈中就是计算结果。

http://www.dtcms.com/a/275638.html

相关文章:

  • JavaScript代码段注入:动态抓取DOM元素的原理与实践
  • GitHub 操作指南:项目协作与自动化工作流实践
  • 【第五节】部署http接口到ubuntu server上的docker内
  • 开源 Arkts 鸿蒙应用 开发(七)数据持久--sqlite关系数据库
  • OSPFv3-一二类LSA
  • 创建 UIKit 项目教程
  • 前端开发中的输出问题
  • 新手向:使用Python将多种图像格式统一转换为JPG
  • 【学习笔记】Linux命令
  • JavaWeb(苍穹外卖)--学习笔记05(MD5)
  • LangChain极速入门:用Python构建AI应用的新范式
  • [特殊字符]LabelMe标注转PaddleSeg数据集:多类掩码自动生成+配置文件输出(附完整Python脚本)
  • Apache Iceberg数据湖高级特性及性能调优
  • 玩转rhel9 Apache
  • linux 系统找出磁盘IO占用元凶 —— 筑梦之路
  • Java零基础笔记12(Java编程核心:面向对象编程高级{常用API、GUI编程})
  • PyTorch多层感知机模型构建与MNIST分类训练
  • 【BurpSuite 2025最新版插件开发】基础篇10(完):日志记录与调试
  • 请求服务端获取broker的机房归属信息异常
  • 剑指offer56_数组中唯一只出现一次的数字
  • JavaScript加强篇——第七章 浏览器对象与存储要点
  • NLP:RNN文本生成案例分享
  • 关于 验证码系统 详解
  • S7-200 SMART PLC:硬件、原理及接线特点全解析
  • Transformer基础
  • Linux驱动09 --- 环境搭建
  • 零基础 “入坑” Java--- 九、类和对象(二)
  • 【YOLOv8-obb部署至RK3588】模型训练→转换RKNN→开发板部署
  • 详解梯度消失和梯度爆炸(反向传播)?
  • 2025年亚太杯(中文赛项)数学建模B题【疾病的预测与大数据分析】原创论文讲解(含完整python代码)