第三章 栈和队列
一、栈
1. 栈空条件: == -1;栈满: == MaxSize – 1; 栈长: + 1;
以上当然是顺序栈的情况。
- 或许之前存储的元素仍然在栈中,但top指针已经指向了新的栈顶,也就起到了删除的作用。
- 进栈操作:指针先加1,再入栈。 [++] = x;
- 出栈操作:先出栈,指针再减1。 x=[--];
注:上述是栈顶指针指向的就是栈顶元素的情况,若指针初始化为=0,则入栈操作变为[++] = x; 出栈操作变为x=[--]。
- 共享栈,仅当两个栈顶指针相邻(top1 – top0 = 1)时,栈满。
- 当不带头结点时,链栈的头指针指向栈顶元素。
- 出栈序列的个数,卡特兰数h(n)=C(2n,n)/(n+1)。
课后题易错:
-
采用非递归方式重写递归程序时必须使用栈。
错误,反例:计算斐波拉契数列迭代实现只需要一个循环即可实现。
- 函数调用时,系统要用栈保存必要的信息。
二、队列
1. 队头(Front)允许删除的一端,队尾(Rear)允许插入的一端。
2. 队列的顺序存储存在“假溢出”问题。无法用 == MaxSize判断队列是否为满。
3. 循环队列:
实现方法:
1.设置标识符(此时队空==0, == maxSize) 2.牺牲一个单元
= = 0;初始:
入队: = ( + 1) % maxSize;
出队: = ( + 1) % maxSize;
队满:( + 1)%maxSize = ;
队空: = ;
队列中元素个数:( – + maxSize)% maxSize;
4. 链队:头指针指向队头结点,尾指针指向队尾结点(单链表中最后一个结点),注意:顺序存储时,尾指针指向队尾元素的下一个位置。
队空: ==
5. 双端队列:
输出受限:允许在一端进入插入和删除,另一端只能插入的双端队列。
输入受限:允许在一端进行插入和删除,另一端只能删除的双端队列。
三、栈和队列的应用
1. 后续表达式中已考虑了运算符的优先级,没有括号。
2. 通过后缀表达式求值:如果是操作数,入栈;如果是运算符,从栈中退出两个操作符Y和X,形成运算指令X<op>Y,再将运算结果入栈。
3. 中缀转后缀的手算方法:将两个直接操作数用括号扩起来,再将操作符提出到括号后,最后再去掉括号。例:((a*(b+c))-d)就写成了abc+*d-;
4. 将递归算法转换为非递归算法,通常需要借助栈来实现这种转换。
5. 队列在计算机系统中的应用,第一个方面是解决主机与外部设备之间速度不匹配的问题,第二个方面是解决由多用户引起的资源竞争问题。
课后题易错:
- 当执行函数时,其局部变量的存储一般采用(栈结构)进行存储。
四、数组、矩阵、广义表
1. 数组是n(n>=1)个相同类型的数据元素构成的有限序列,每个数据元素称为一个数组元素。
2. 数组是线性表的推广。一维数组可以看做是一个线性表;二维数组可以看做是元素是线性表的线性表。
3.(矩阵)压缩存储:指为多个值相同的元素只分配一个存储空间,对零元素不分配存储空间。其目的是为了节省存储空间。
4. 对稀疏矩阵进行压缩存储,常用的两种方法是(三元组和十字链表)。
5. 三元组(行标,列标,值),稀疏矩阵压缩存储后便失去了随机存取特性。
6. 广义表
广义表的长度:为表中最上层元素的个数。
广义表的深度:为表中括号的最大层数。
表头和表尾:当广义表非空时,第一个元素为广义表的表头,其余元素组成的表是广义表的表尾。
头尾链表存储结构:原子结点有2个域:标记域和数据域、广义表结点有3个域:标记域、头指针域与尾指针域(其中标记域用于区分当前结点是原子(用0表示)还是广义表(用1表示),头指针域指向原子或者广义表结点,尾指针域为空或者指向本层的下一个广义表结点)。