栈的总结_legend

时间:2023-01-04 21:58:28




栈stack:

(1)栈的基本知识:

 

        (1.1)栈的存储结构:

        (1.2)栈的特点:

(2)栈的基本操作:

        (2.1)顺序栈的基本操作:

        (2.2)链式栈的基本操作:

(3)顺序栈:seqStack

(4)链式栈:linkStack

(5)共享栈:shareStack

(6)栈的应用:

        (6.1)表达式求值:expressionValue

        (6.2)括号匹配match:

        (6.3)求解迷宫问题:maze

(7)栈的扩展操作:

        (7.1)       O(1)求栈中最小值:

 

-------------------------------------------

(1)栈的基本知识:

 

        (1.1)栈的存储结构:

        顺序栈,链式栈;

 

        (1.2)栈的特点:

 

        后进先出,头进头出,插入和删除在栈顶进行;

        栈是一种插入删除受限制的线性表。

 

(2)栈的基本操作:

        (2.1)顺序栈的基本操作:

                  (2.1)初始化栈init:

                  (2.2)栈空isEmpty:

                  (2.3)栈满isFull:

                  (2.4)进栈push:

                  (2.5)出栈pop:

                  (2.6)取栈顶getTop:

                  (2.7)栈的大小:getSize:

 

        (2.2)链式栈的基本操作:

                  (3.1)初始化栈init:

                  (3.2)栈空isEmpty:

                  (3.3)进栈push:

                  (3.4)出栈pop:

                  (3.5)取栈顶getTop:

                  (2.6)栈的大小:getSize:

                  (注:链式栈不存在栈满)

 

(3)顺序栈:seqStack

 

顺序栈通常用一个数组来存储栈中元素,用下标为0的一端作为栈底,

栈顶设置一个指针top指示栈中元素的变化,称为栈顶指针。

 

        (3.1)顺序栈的定义:

typedefstruct{


ElemTypearray[Maxsize];


inttop;


}SqStack;

        (3.2)顺序栈的五要素:

 

                  (3.2.1)方法一:

                  .       栈空条件:s.top=-1

                  .       栈满条件: s.top=Maxsize-1

                  .       元素e进栈:s.top++;s.array[s.top]=e;

                  .       元素出栈:e=s.array[s.top];s.top--;

                  .       获取栈顶: returns.array[top];

 

                  解析:初始化top=-1;则当前的top这个位置,已经被填入了元素;

                  所以进栈需要top++;然后赋值;

                  出栈,直接去top处的值,然后top--;

                  栈满的条件是top=Maxsize-1;

                  获取栈顶: returnarray[top];

 

                  (3.2.2)方法二:

 

                  .       栈空条件:s.top=0

                  .       栈满条件: s.top=Maxsize

                  .       元素e进栈:s.array[s.top]=e;s.top++;

                  .       元素出栈:s.top--;e=s.array[s.top];

                  .       获取栈顶: returns.array[top-1];

 

                  解析:初始化top=0,表示当前top这个位置还没有元素填充,

                  填充的是top-1;

 

        (3.3)顺序栈的基本操作代码:

 

 

(4)链式栈:linkStack

        (4.1)链式栈的定义:

typedefstruct linkNode{


elemTypeelement;


linkNode*next;


}linkNode;





class linkStack{


public :


linkNode* topNode;


int size;/*可有可无*/


}

 

        (4.2)链式栈的操作:

        .       栈空:topNode=NULL orsize=0;

                  (不带头节点的链式栈)

        .       进栈:头插法:建立一个newnode,更新topNode;

        .       出栈:删除首节点,更新topNode;

 

        (4.3)链式栈的基本操作代码:

 

(5)共享栈:shareStack

        (5.1)共享栈的图解:

栈的总结_legend

        (5.2)共享栈的解析:

 

        两个栈共享一个数组vector[0~MaxSize-1]的空间,从而构成共享栈,数组vector的两端是固定的,分别作为栈1,和栈2的栈底。

 

        (5.3)共享栈的操作:

                  (5.3.1)栈1的操作:

                  .       栈空: top1=-1;

                  .       栈满: top1=top2-1;

                  .       元素e进栈: top1++;shareArray[top1]=e;

                  .       出栈:e=shareArray[top1];top1--;

 

                  (5.3.2)栈2的操作:

                .       栈空:top2=MaxSize-1;

                  .       栈满: top2=top1+1;

                  .       元素e进栈: top2--;shareArray[top2]=e;

                  .       元素出栈:e=shareArray[top2];top2++;

 

                  (5.4)共享栈的操作代码:


(6)栈的应用:

 

        (6.1)表达式求值:expressionValue:

 

                  (6.1.1)解析:()、*/、+-这几种符号的优先级是不一样的,中缀表达式是有优先级的表达式,不便于在程序中处理,后缀表达式是一种非优先级的表达式,而且不会出现括号。

                  (6.1.2)步骤:

                           (1)中缀表达式转后缀表达式:

 

                           分析:     后缀表达式与表达式的操作数的排列次序完全相同,只是运算符改变了次序。

 

                           所以:

                           (1)若读到一个操作数,就把它作为后缀表达式的一部分输出;

                           (2)对于运算符的处理,系统需设置一个存放运算符的栈。

 

                           分析:初始时,栈顶设置一个界限符#(与表达式结束符#配成一对)

     每当读到一个运算符时,就将其优先级与栈顶位置运算符优先级进行比较,以决定是把所读到的运算符进栈,还是将栈顶位置的运算符作为后缀表达式的一部分输出。

 

     因为:     对于任意两个相继出现的运算符θ1θ2,它们之间的优先关系至多是下面三种关系之一:

 

       θ1<θ2,θ1的优先级低于θ2;

                   θ1=θ2,θ1的优先级等于θ2;

                   θ1>θ2,θ1的优先级高于θ2。

 

             (2)优先级解析:

 

             对于+,-,*,/,(,),#,这几种运算符来说,其优先关系可以由算术四则运算规则得到。

                 (1)先乘除,后加减;

                           (2)从左到右算;

                           (3)先括号内,后括号外。

                           A、由(1)*,/ > +,-;

                           B、由(2)*>/,/ >*, +>-,->+;

                           C、由(2)对于+,-,*,/,当θ1=θ2时,令θ1>θ2,即+>+,->-,*>*,/>/;

                           D、由(3)+,-,*,/的优先级均低于“(”,但高于“)”;

                           (注:即:+,-,*,/的优先级均低于它们后面的“(”。

                           高于它们后面的“)”。

                           )

 

                           E、由(3)“(”的优先级均低于+,-,*,/,(;

                    “)”的优先级均高于 +,-,*,/,);

              (注:即:“(”的优先级均低于它后面的+,-,*,/,( 。

              “)”的优先级均高于它后面的+,-,*,/,)

              )

 

 

                           F、“(” =“)”,表示当左右括号相遇时,括号内的运算已经完成;

                           

                           H、“#”是表达式的结束符,为了算法简洁,在表达式的最左边也需设一个“#”,构成整个表达式的一对括号;

                           左“#”的优先级低于+,-,*,/,(;

                            +,-,*,/,)的优先级高于“#”(结束符);

                            “#”=“#”表示整个表达式处理完毕。

 

                            注意:“)”与“(”,“#”与“)”以及“(”与“#”之间无优先关系,因为表达式中不允许它们相继出现(若出现,则表达式有错),一旦遇见,则可以认为出现了语法错误。

--------------------

                            中缀表达式转为后缀表达式的算法步骤:

 

(1)置运算符栈s为空栈,然后将表达式的起始符“#”入栈;

(2)循环:依次读入中缀表达式中一个单词;

 

        A、若是操作数,就将其输出,接着读下一个字符;

        B、若是运算符,就赋予x2,比较x2与栈顶运算符x1的优先级;

                  1.     若x2的优先级高于x1,则将x2进栈,读下一个单词;

                  2.     若x2的优先级低于x1,x1退栈,并作为后缀表达式的一个单词输出,再转B(即继续比较x2与新的栈顶运算符x1);

                  3.     若x2的优先级等于x1,且x1为“(”,x2为“)”,则x1退栈,然后继续读下一个单词;

                  4.     若x2的优先级等于x1,且x1为“#”,x2也为“#”,则算法结束。

 

范例:

                  图解1:中缀-后缀1

栈的总结_legend

                  图解2:中缀-后缀2


 

栈的总结_legend

                           (2)后缀表达式求值:

                           思路:遍历后缀表达式,遇到非操作符的字符则直接压入栈中,如果遇到操作符则从栈中弹出两个对象,进行对应的操作,然后将计算的结果又压入栈中。继续遍历,直到表达式被遍历完成,此时栈中保存的值也就是当前表达式的值。

 

                           注意:除法和减法的操作数顺序问题以及除数不能为0的,因为第一次退栈的操作数是运算符后的操作数,第二次退栈的操作数是运算符前的操作数。

 

                  (6.1.3)中缀表达式->后缀表达式:

                  

                           中缀表达式:a*b+c*d-e/f

                           后缀表达式:ab*cd*+ef/

 

                  (6.1.4)表达式求值代码实现:

 

代码实现2(简洁版):

 

 

        (6.2)括号匹配match:

 

 

        (6.3)求解迷宫问题:maze

        

        (6.4)进制转换:

 

                  (6.4.1)图解:

栈的总结_legend

                  (6.4.2)思想:

                  如:十进制整数转换成n进制:除n取余倒着数(栈实现)

 

                  (6.4.3)代码实现



 

 

 

 

        (6.5)路径探索之保存路径:

 

 

(7)栈的扩展操作:

 

(7.1)       O(1)求栈中最小值: