第3章 栈和队列知识点
从数据结构的角度来看,栈和队列也是线性表,其特殊性在于它们的基本操作是线性表操作的子集,是操作受限的线性表,因此被称为限定性的数据结构。
3.1 栈
1. 概念:栈是限定仅仅在表尾进行插入或删除操作的线性表。表尾称为栈顶,表头称为栈底;不含元素的空表称为空栈。
2. 特点:后进先出(LIFO),先进后出(FILO)
3. 栈的表示和实现——存储结构
(1)顺序栈
实现:一维数组s[M]
栈顶指针top,指向实际栈顶后的空位置,初值为0;
当top=0,栈空,此时出栈,则下溢出;当top=M,栈满,此时入栈,则上溢。

(2)链栈
——还不是很懂 可能和链表有关
4. 栈的应用
(1)过程的嵌套调用
示例代码,自己运行时到4750终止,显示栈满:
#include<stdio.h>
void foo(i)
{
printf("%d\n", i);
foo(i + 1);
}
int main(int argc, char* argv[])
{
int i=0;
foo(i);
}
(2)递归过程及其实现
递归:函数直接或简介的调用自身
实现:建立递归工作栈
例子.递归的执行情况分析:
#include<stdio.h>
void print(int w)
{
int i;
if (w != 0)
{
print(w - 1);
for (i = 1; i <= w; i++)
printf("%3d", w);
printf("\n");
}
}
int main()
{
int j = 3;
print(3);
}
//运行结果
1
2 2
3 3 3
(3)回文游戏:顺读与逆读字符串一样(不含空格)
实现1:利用数组
找到数组的中间记为mid,最后一个元素记为L
i -> 0~mid
j -> L-i~mid
实现2:利用栈
读入字符串 - 去掉空格(原串) - 压入栈 - 原串字符与出栈字符依次比较,若不等,非回文。若直到栈空都相等,回文。
(4)多进制输出
例:把十进制数159转换为八进制数
个位数先进站
(5)表达式求值
中缀表达式:a*b+c、a+b*c、a+(b*c+d)/e
后缀表达式(逆波兰式):ab*c+、abc*+、abc*d+e/+
具体实现:
中缀表达式:操作数栈和运算符栈
e.g:计算表2+4-3*6 能算的先算并弹出,将得到的结果填入
后缀表达式求值步骤:
1. 读入表达式一个字符
2. 若是操作数,压入栈,转4
3. 若是运算符,从栈中弹出两个数,将运算结果再压入栈
4. 若表达式输入完毕,栈顶即表达式;若表达式未输入完,转1
e.g:24+36*- 自己画图示意
3.2 队列
概念:只允许在表的一端进行插入,在表的另一端删除元素的线性表。允许插入的一端叫队尾,允许删除的一端则称为队头。
特点:先进先出(FIFO,LILO)
链队列
(1)结点定义:
typedef struct node
{
int data;
struct node*link;
}JD;
(2)设队首指针 front和rear,front指向头结点,rear指向队尾
工作原理:
队列的顺序存储结构
实现:用一维数组实现 sq[M]
(1)设两个指针front ,rear约定:rear指示队尾元素,front指示队头元素前一位置,初值front=rear=-1
存一个,rear后移一个;出一个,front下移一个
(2)空队列条件:front==rear 入队列:sq[++rear]=x 出队列:x=sq[++front] 啥意思
存在问题:
设数组维数为M,则:
当front=-1,rear=M-1时,再有元素入队时发生溢出——真溢出;
当front!=-1,rear=M-1时,再有元素入队是发生溢出——假溢出。(图上最右边)
解决方案
1. 队首固定, 每次出队剩余元素向下移动——浪费时间
2. 循环队列:
(1)基本思想:把队列设想成环形,让 sq[0] 接在sq[M-1]之后,若rear+1==M,则令rear=0。
(rear+1==M时,意味着环形到头了)
(2)队空:front==rear 队满:front==rear 问题~如何判断??
解决方案:
(1)另设一个标志以区别队空、队满
计数count——队列中有效元素个数:
队列为空时,count == 0
当有元素入队时,count++,当count和队列的maxsize相等时,代表队列已满
(2)少用一个元素空间 是啥??
队空:front==rear; 队满:(rear+1)%M==front