定义 | 只能在表的一端进行插入和删除的线性表 |
---|---|
逻辑结构 | 数据元素之间是一对一的关系 |
存储结构 | 顺序存储或链式存储 |
运算规则 | 只能在栈顶运算,且访问结点时依照后进先出(LIFO)或先进后出(FILO)的原则 |
基本操作 | 建栈、判断栈满或栈空、入栈、出栈、取栈顶元素值 |
定义:利用一组地址连续的存储单元,依次存放从栈底到栈顶的数据元素。
$$ PUSH: s->ele[s->top++] = a_{n+1} $$
$$ POP: (s->top)--, e = s->ele[s->top] $$
注:顺序栈不仅需要判断下溢(栈空),还需要判断上溢(栈满)。
定义:栈的链式存储结构,简称链栈;与单链表类似链表的尾部是栈底,链表的头部是栈顶。
问题:对算术表达式求值:1 + 2 * 4 - 9/3
解法
对每种运算符赋予一个优先数,如:
* | / | + | - | # |
---|---|---|---|---|
2 | 2 | 1 | 1 | 0 |
其中#是表达式结束符。
一般设两个栈:
中缀表达式 a + b*c + (d * e + f) * g,其转换成后缀表达式则为 a b c * + d e * f + g * +。转换过程需要用到栈,具体过程如下:
1)如果遇到操作数,我们就直接将其输出。
2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。
5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
栈的特性:
问题:用不多于四种颜色对地图着色,使相邻地区不重色。
解法:
detail:
使用一个关系矩阵存储地区与地区之间是否相邻
伪代码:
定义:若一个过程直接地或间接地调用自己,则称这个过程是递归的。
分类:直接递归与间接递归。
条件:
解决问题时,可把一个问题转化为一个新的问题。
这个新问题的解法与原问题的解法相同,只是所处理的对象不同。
必须有结束递归的条件,否则递归将无休止地进行,导致耗尽系统资源。
数据结构是递归的,如二叉树。
问题的解法是递归的,如汉诺塔、地图四染色、走迷宫等。
大问题转换为几个小问题,小问题进一步分解为更小的小问题,直到递归出口为止。
递归模型由递归出口和递归体两部分组成,前者确定递归合适为止,后者确定递归的方式。 $$ n! = \begin{cases} & \text 1 ,n=0\ & \text n*(n-1)!, n>=1 \end{cases} $$
递归算法的非递归描述:考虑到**栈帧的模型(系统栈的调用)**就很好理解。
两种解法的时间复杂度与空间复杂度都是一样的。
队列定义 | 只能在表的一端进行插入,在表的另一端进行删除的线性表 |
---|---|
逻辑结构 | 元素之间是一对一的关系 |
存储结构 | 顺序队列和链队列 |
运算规则 | 队尾入队、队头出队、遵循先进先出(FIFO)的原则 |
基本操作 | 入队、出队、建空队列、判队空或对满 |
队列的顺序存储,称为顺序队列。由存放元素的顺序表、队头指针、队尾指针三部分组成。
顺序存储的两个问题:
普通队列出现的假上溢的问题:使用循环队列解决:
把队列设想为环形(若 rear+1 == M, 则令 rear=0)
实现:利用模运算
入队:rear = (rear + 1)%M; sq[rear] = x;
出队: front = (front + 1)%M; x = sq[front];
队空与队满的判定条件相同:少用一个元素空间
初始化:
入队:
出队:
初始化:
入队:
出队:
运动会设立了 n 个比赛项目,没饿过运动员可以参加 1~3 个项目。请问应该如何安排比赛日程?从而使同一运动员参加的项目不能在同一时间进行,并使总的竞赛日程最短。
解决方法概述:
将集合 A 中的所有元素放入一个队列中,然后依次取出队头元素 a_i 放入一个待分配的组 gm 中,若 a_i 与组 gm 中的其他元素无冲突,则加入组 gm,如产生冲突,则将重新入队;当遍历考察一轮队列中的所有元素后,产生一个无冲突的子集 gm,如此循环,直到所有元素都被分配完成。
细节:
准备
顺序存储实现队列
链式存储实现队列
测试
添加冲突
主函数