§3.1 栈
3.1.1 抽象数据类型栈的定义
栈是限定仅在表尾进行插入或删除操作的线性表。因此,对栈来说,表尾端有其特殊含义,称为栈顶。相反地,表头端称为栈底。
栈是后进先出(LIFO)的线性表。
基本操作:
top() 返回栈顶元素
pop() 弹出栈顶元素
push(a) 将元素a压入栈
empty() 判断是否为空
size() 返回元素个数
3.1.2 栈的表示和实现
①顺序栈 可用一个三个元素结构体+数组实现
typedef struct { SElemType *base; SElemType *top; int stacksize; }SqStack;
其中stacksize指示栈的当前可使用的最大容量。栈的初始化操作为:按设置的初始分配量进行第一次储存分配,base可称为栈底指针,在顺序栈中,它始终指向栈底的位置,若base的值为NULL,则表明栈结构不存在。称top为栈顶指针,其初值指向栈底,即top=base可作为栈空的标记,每当插入新的栈顶元素时,指针top增1;删除栈顶元素时,指针top减1,因此,非空栈中的栈顶指针始终在栈顶元素的下一个位置上。
②链栈 用链表实现 不再详述
§3.2 栈的应用举例
3.2.1 数制转换
十进制数N = (d进制) (N整除d)*d + N%d 可以用栈来模拟
void conversion() { //对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数 InitStack(S); scanf("%d",&N); while(N) { Push(S,N%8); N = N/8; } while(!StackEmpty(S)) { Pop(S,e); printf("%d",e); } }3.2.2 括号匹配的检验
检验一系列括号是否匹配的方法可以用“期待的急迫程度”这个概念来描述。在算法中设置一个栈,每读入一个括号,若是右括号,则或者使置于栈顶的最急迫的期待得以消解,或者是不合法的情况;若是左括号,则作为一个新的更急迫的期待压入栈中,自然使原有的在栈中的所有未消解的期待的急迫性都降了一级。另外,在算法的开始和结束,栈都应该是空的。
3.2.3 行编辑程序
3.2.4 迷宫求解
搜索(DFS)
3.2.5 表达式求值
§3.3 栈与递归的实现
递归:①有递归定义的数学函数 ②有递归特性的数据结构(二叉树 广义表等) ③八皇后等搜索问题
※Hanoi塔问题
void hanoi(int n,char x,char y,char z) { //将塔座x上按直径由小到大且自上而下编号为1-n的n个圆盘规则搬到 //塔座z上,y可用作辅助塔座 //搬动操作move(x,n,z)可定义为(c是初值为0的全局变量,对搬动计数): //printf("%d.Move disk %d from %c to %c\n",++c,x,z); if(n == 1) move(x,1,z); else { hanoi(n-1,z,y); move(x,z); hanoi(n-1,y,z); } }
§3.4 队列
3.4.1 抽象数据类型队列的定义
队列(queue)是一种先进先出(FIFO)的线性表,它只允许在表的一端进行插入,而在另一端删除元素。允许插入的一端叫队尾(rear) 允许删除的一端叫做队头(front)
双端队列:限定插入和删除操作在表的两端进行的线性表。
各种变形:输出/入首先的双端队列(如限定双端队列从某端点插入的元素只能从该端点删除则退化成两个栈底相邻的栈)
3.4.2 链队列——队列的链式表示和实现
3.4.3 循环队列——队列的顺序表示和实现
顺序队列:用数组模拟队列,两个指针front和rear分别指示队列头元素及队列为元素的位置,插入新元素时,尾指针增1,删除队列头元素时,头指针增1.所以在非空序列中,头指针指向头元素,尾指针指向尾元素的下一个位置。
循环队列:为队列臆造一个环状的空间来节约空间。