当前位置:文档之家› 数据结构中栈的介绍

数据结构中栈的介绍

数据结构中栈的介绍1.栈的概念栈(Stack)是一种特殊的表,这种表只在表的一端进行插入和删除操作。

允许插入和删除数据元素的这一端称为栈顶;而另一固定的一端称为栈底。

不含任何元素的栈称为空栈。

栈的修改是按后进先出的原则进行的。

栈又称为后进先出(Last In First Out)表,简称为LIFO表。

如图1所示:假设一个栈S中的元素为a n,a n-1,..,a1,则称a1为栈底元素,a n为栈顶元素。

图1 图 22.栈的存储与操作由于栈是一个特殊的表,可以用一维数组来实现栈。

同时设立指针t(称为栈顶指针)来指示栈顶元素的当前位置。

我们用一个数组s[1..m]来表示一个栈时,将栈底固定在数组的底部,即s[1]为最早入栈的元素,并让栈向数组上方(下标增大的方向)扩展。

当t=0时,表示这个栈为一个空栈。

当t=m时,表示这个栈已满。

可以用下列方式定义栈:constm=栈表目数的上限;typestack=array[1..m] of stype; {栈的数据类型}vars:stack;t:integer; {栈顶指针}进栈、出栈操作的过程和函数(假设栈元素的数据类型为整型):(1)进栈过程(push)①若t≥m时,则给出溢出信息,作出错处理(进栈前首先检查栈是否已满,满则溢出;不满则作②);②置t=t+1(栈指针加1,指向进栈地址);③S(t)=x,结束(x为新进栈的元素);procedure push(var s:stack; x:integer;var t:integer);beginif t=m then writeln('overflow')elsebegint:=t+1;s[t]:=x;endend;(2)退栈函数(pop)①若t≤0,则给出下溢信息,作出错处理(退栈前先检查是否已为空栈,空则下溢;不空则作②);②x=s(t),(退栈后的元素赋给x);③t=t-1,结束(栈指针减1,指向栈顶)。

function pop(var s:stack;var t:integer):integer;beginif t=0 then writeln('underflow')elsebeginpop:=s[t];t:=t-1;endend;(3)读栈顶元素函数(top)function top(var s:stack; t:integer):integer;beginif t=0 then writeln('underflow')elsetop:=s[t];end;3栈的应用举例【例10-4】.设栈S的初始状态为空,元素a,b,c,d,e,f,g依次入栈,以下出栈序列不可能出现的是()。

A.a,b,c,e,d,f,gB.b,c,a,f,e,g,dC.a,e,d,c,b,f,gD.d,c,f,e,b,a,gE.g,e,f,d,c,b,a题解:此题可以采用模拟的方法,依次判断各个选项是否能出现。

如A,每个元素依次进栈然后出栈,即得到此序列。

再来看B,a,b进栈,然后b出栈,c进栈后出栈,a出栈,d,e,f进栈,f,e出栈,g进栈后出栈,d出栈,可以满足。

依此类推,发现只有E不能满足,答案为E。

【例10-5】.如下图,有一个无穷大的的栈S,在栈的右边排列着1,2,3,4,5共五个车厢。

其中每个车厢可以向左行走,也可以进入栈S让后面的车厢通过。

现已知第一个到达出口的是3号车厢,请写出所有可能的到达出口的车厢排列总数。

出口←←S↓题解:首先必是1,2,3进栈,然后3出栈,此时栈中有元素1,2,未进栈元素有4,5。

我们可以分情况讨论,由于2一定在1之前出栈,我们可以讨论4,5的出栈顺序,如下:(1)4先出栈:此时相当于4,5不经过栈直接到出口。

相当于1,2,4,5四个数字的一个/4=6(种)。

排列,2排在1前,4排在5前,共有种数44(2)5先出栈:此时4和5的出栈顺序必连续,有以下三种排列:5 4 2 1;2 5 4 1;2 1 5 4。

综上所述,总的排列数是9种。

【例1】计算后缀表达式题目描述数学上使用的是中缀表达式,在中缀表达式中需要使用括号来改变运算的优先级。

事实上我们可以用后缀表达式或前缀表达式,这两种表达式里就可以完全避免使用括号。

后缀表达式:运算符放在两个运算对象之后。

所有计算按运算符出现的顺序,由左而右进行。

例如:3*(5-2)+7 对应的后缀表达式为3.5.2.- *7.+@现有一后缀表达式,让你求表达式的值,已知运算符仅限于"+","-","*","/"四种运算。

输入@表示表达式结束,’.’为操作数的结束符。

如:后缀表达式3.5.2.- *7.+@的值为16。

输入一个后缀表达式,无需判错,“/”作为整除运算。

输出后缀表达式的值,一个整数。

参考程序:program ex10_6;constn=30;typestack=array[1..n] of integer;vars:stack;a:string;t,i,j,k,q:integer;procedure push(var s:stack; x:integer;var top:integer);beginif top=n then writeln('overflow')elsebegintop:=top+1;s[top]:=x;endend;function pop(var s:stack;var top:integer):integer;beginif top=0 then writeln('underflow')elsebeginpop:=s[top];top:=top-1;endend;begini:=1; t:=0;readln(a);while a[i]<>'@' dobegincase a[i] of'0'..'9' :begink:=0;repeatk:=10*k+ord(a[i])-ord('0');i:=i+1;until a[i]='.' ;push(s,k,t); {数字进栈}end;'+' : push(s,pop(s,t)+pop(s,t),t); {取栈首的两个数值相加}'-' :beginj:=pop(s,t);push(s,pop(s,t)-j,t);end;'*' : push(s,pop(s,t)*pop(s,t),t); { 取栈首的两个数值相乘}'/' :beginj:=pop(s,t);push(s,pop(s,t) div j,t);end;end;i:=i+1;end;q:=pop(s,t); {最后栈中的元素即为答案}writeln(q);end.【例2】背包问题假设有n件质量为w1,w2,...,w n的物品和一个最多能装载总质量为T的背包,能否从这n件物品中选择若干件物品装入背包,使得被选物品的总质量恰好等于背包所能装载的最大质量,即w i1+w i2+...+w ik=T。

若能,则背包问题有解,否则无解。

算法思想首先将n件物品排成一列,依次选取;若装入某件物品后,背包内物品的总质量不超过背包最大装载质量时,则装入(进栈);否则放弃这件物品的选择,选择下一件物品试探,直至装入的物品总和正好是背包的最大转载质量为止。

这时我们称背包装满。

若装入若干物品的背包没有满,而且又无其他物品可以选入背包,说明已装入背包的物品中有不合格者,需从背包中取出最后装入的物品(退栈),然后在未装入的物品中挑选,重复此过程,直至装满背包(有解),或无物品可选(无解)为止。

具体实现设用数组w[1..N],stack[1..N]分别存放物品重量和已经装入背包(栈)的物品序号,tot表示背包的剩余最大装载量。

每进栈一个物品,就从tot中减去该物品的质量,设i为待选物品序号,若tot-w[i]>=0,则该物品可选;若tot-w[i] < 0,则该物品不可选,且若I=n,则需退栈,若此时栈空,则说明无解。

参考程序:program ex10_7;var t,n,i:integer;w,stack:array[1..100]of integer;function knap(tot:integer):boolean;vari,top:integer;begintop:=0;i:=1;while (tot>0)and (i<=n)dobeginif (tot-w[i]>=0)and(i<=n) then begintop:=top+1;stack[top]:=i;tot:=tot-w[i];end;if tot=0 then exit(true){正好装满则返回true}else beginif (i=n)and(top>0)then{I=n时退栈}begini:=stack[top];dec(top);tot:=tot+w[i];if (i=n)and(top>0) thenbegin{如退栈后I=n,即退栈的元素是最后一个,则需再次退栈,因为此时已无法选择下一个物品}i:=stack[top];dec(top);tot:=tot+w[i];end;end;inc(i);end;end;exit(false);end;beginreadln(t,n);for i:=1 to n do read(w[i]);if knap(t) then writeln('Yes')else writeln('No');end.。

相关主题