限定性:限制线性表插入和删除等运算的位置。(只允许在端点位置操作)
栈:把运算位置限定在表尾端的线性表。
栈顶:允许运算端
栈尾:不允许运算端
栈顶指示器:用来指示动态变化的栈顶位置
空栈:表中无任何元素
满栈:无法申请到栈区可用空间
栈的常见运算:进栈或入栈(表尾插入),出栈或退栈(表尾删除)
上溢:栈已满还要入栈
下溢:栈已空还要出栈
栈的特性:后进先出
栈的抽象数据类型的三要素:元素,关系,操作
数据元素:可以是任意类型的数据,但必须属于同一个数据对象
关系:栈中数据元素之间是线性关系
基本操作:初始化,清栈,判栈是否为空,判栈是否为满,进栈,出栈,读栈顶
存储方式:顺序存储,链式存储
两栈共享:进栈需判栈满(S->top[0]+1==S->top[1])(注:top指向的是位置而不是个数,像S->top[0]+S->top[1]==M这样的表述是错的) 出栈需判栈空(写成S->top[0]==-1&&S->top[1]==M是不对的,因出某一个栈时另一栈为空是没有影响的,需要出哪个栈,对哪个栈进行判断就可以了)
链栈:1.链栈就是链式存储的栈,采用带头结点的单链表实现链栈,头指针就作为栈顶指针。
2.top为栈顶指针,始终指向当前栈顶元素前面的头结点。若top->next==NULL,则代表空栈。
3.链栈在使用完毕时,应该释放其空间。
4.入栈:s->next=top->next;top->next=s;
顺序栈与链栈判满的区别:顺序栈判满与数组定义长度有关,链栈判满与可否申请系统空间有关
设计递归算法的方法:1.使用递归算法的前提:
(1)原问题可以层层分解为类似的子问题,且子问题比原问题的规模更小;
(2)规模最小的问题具有直接解。
2.设计递归算法的原则是用自身的简单情况来定义自身。
3.设计递归算法的方法是:
(1)寻找分解方法:将原问题转化为子问题求解;
(2)设计递归出口:即根据规模最小的子问题,确定递归终止条件。
递归过程的实现:1.递归进层:(i->i+1层)
(1)保留本层参数与返回地址;
(2)给下层参数赋值;
(3)将程序转移到被调函数的入口;
2.递归退层:(i<-i+1层)
(1)保存被调函数的计算计算结果;
(2)恢复上层参数(释放被调函数的数据区);
(3)依照被调函数保存的返回地址,将控制转移回调用函数。
递归函数的运行过程:1.调用函数和被调函数是同一个函数,与每次调用相关的是递归运行的层次;
2.递归函数的进层退层:设该递归函数的主函数是第0层,则从主函数调用递归函数进入第1层,从第i层调用此函数为进入下一层即i+1层,反之函数退出第i层递归应返回上一层,即i-1层;
3.递归机制支持:系统设立一个递归工作栈作为递归函数运行使用的存储区,每次递归需要所需信息构成一个工作记录,包括实参、局部变量以及上一层的返回地址。每进入一层递归,就产生一个新的工作记录压入栈顶,每退出一层递归,就从栈顶弹出一个工作记录。
递归算法的两个特性:1.递归算法是一种分而治之、把复杂问题分解为简单问题的求解问题方法,对求解某些复杂问题,递归算法分析方法是有效的。
2.递归算法的时间效率差,其时间效率低。
消除递归的原因:1.有利于提高算法时空性能,因为递归执行时需要系统提供隐式栈实现递归,效率低且费时。
2.无应用递归语句的语言设施环境条件,有些计算机语言不支持递归功能,如FORTRAN、BASIC语言
3.递归算法是一次性执行完,这在处理有些问题时不合适,也存在把递归算法转化为非递归算法的需求
消除递归的方法:一类是简单递归问题的转化,对于尾递归和单向递归的算法,可用循环结构的算法替代;另一类是基于栈的方式,即将递归中隐含的栈机制转化为由用户直接控制的明显的栈,利用栈保存参数。
单向递归:递归函数中有一处以上的递归调用语句,但各次递归调用语句的参数只和主调用函数有关,相互之间参数无关,且这些递归调用语句处于算法的最后。
尾递归:递归调用语句只有一个且且处于算法的最后,尾递归是单向递归的特例。
栈与递归的关系:栈可以支持递归的实现。