1.总述
栈和队列是两种常用且重要的数据结构,本质还是线性表,但限定插入和删除只能在表的端点。
1.栈:插入时只能添加到表尾(即插入到n+1);删除时只能从最后一个开始删除。即:后进先出!
2.队列:插入时只能添加到表尾(即插入到n+1);删除时只能从第一个开始删除。即:先进先出!
2.栈的定义和特点:
栈stack:仅在表尾进行插入、删除操作的线性表,顺序栈更常见。其操作特点为后进先出。
表尾(即an端)称为栈顶;表头(即a1端)称为栈底,通常用s表示一个栈。
插入一个元素到栈顶(表尾)称入(压)栈/push;从栈顶(表尾)删除一个元素称出(弹)栈/pop。
体现操作特点举例:
总结:与普通线性表只有运算规则不同,栈的运算规则规定只能从栈顶,但线性表是随机存取。
3.队列的定义和特点:
队列queue:只能在表尾插入,只能从表头删除的线性表,顺序队列更常见。其操作特点是先进先出。
表尾(即an端)称为队尾;表头(即a1端)称为队头,通常用q表示一个队列。
则入队和出队要遵循从尾到头的方向,头删尾插。
总结:
4.案例引入:
1)进制转换:
2)括号匹配的检验:
3)表达式求值:利用算符优先算法:
4)舞伴问题
5.栈的表示与操作的实现
1)栈的抽象数据类型定义:
2)栈的顺序表示和实现(顺序栈):
存储方式: 同一般线性表的顺序存储结构完全相同,利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。栈底一般在低地址端。
附设top指针,指示栈顶元素在顺序栈中的位置;另设base指针,指示栈底元素在顺序栈中的位置。
空栈标志:base==top;此时若继续出栈操作则称为下溢,通常认为是一种结束条件;
满栈标志:top-base==stacksize;此时若继续入栈操作则称为上溢,通常认为是一种错误;
注意:top和base相当于两个指针,也可以直接做减法运算,意为两个指针之间差距的元素个数。
栈满后的处理:1.报错;2.分配更大的空间,作为栈的存储空间,将原栈的内容移入新栈。
顺序栈的数据类型定义:
3)顺序栈的操作:
--顺序栈的初始化:
--判断顺序栈是否为空:
--求顺序栈长度:
--清空顺序栈:无论内存空间里面是不是空的,只要top==base就认为栈空:
--销毁顺序栈:释放栈所在的内存空间:
--顺序栈的入栈:
思路为:判断栈是否已满-->元素存储到top指针所指的位置-->top指针再上移;
--顺序栈的出栈:
思路为:判断栈是否已空-->top指针先下移-->元素存储到top指针所指的位置;
4)栈的链式表示与实现(链栈):
--链栈的初始化:
--判断链栈是否为空,即判断头指针是否为空:
--链栈的入栈:
--链栈的出栈:
--取链栈栈顶元素:
6.栈与递归
递归:若一个对象部分地包含它自己或用它自己给自己定义,则称这个对象是递归的;若一个过程直接地或间接地调用自己,则称这个过程是递归的过程。
7.队列的表示与操作的实现
1)队列的类型定义:
a1为队头,an为队尾,头删尾插。
2)队列的顺序表示和实现(即顺序队):
入队和出队的过程如下,其中队空:front==rear;:
真溢出/假溢出:
解决假溢出的方法:
继而引出循环队列:利用模运算实现:
循环队列的类型定义:
问题:队满/队空如何区别? 常用方法为3.少用一个元素空间:
3)循环队列的操作:
--队列的初始化:
--求队列的长度,即求队列中元素的个数:
--循环队列的入队:
--循环队列的出队:
--取队头元素:
4)队列的链式表示和实现(即链队):
若用户无法估计所用队列的长度,则宜采用链队。
链队列的类型定义:
链队列运算指针变化状况:
链队列的操作:
--链队列的初始化:
--链队列的销毁:
--链队列的入队(将元素e入队),只能入到队尾:
--链队列的出队(将元素e出队),只能删队头:
注意:如果头结点的下一个元素正好就是尾结点,意思就是删除的恰好是尾结点,则还要让尾指针也指向头结点;
--取链队列的队头元素:
以上即为栈和队列的所有基本内容。