数据结构中栈的介绍
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构中栈的介绍
1.栈的概念
栈(Stack)是一种特殊的表,这种表只在表的一端进行插入和删除操作。
允许插入和删除数据元素的这一端称为栈顶;而另一固定的一端称为栈底。
不含任何元素的栈称为空栈。
栈的修改是按后进先出的原则进行的。
栈又称为后进先出(Last In First Out)表,简称为LIFO 表。
如图1所示:假设一个栈S中的元素为a,a,..,a,则称a为栈底元素,a为栈顶元nn1n-11素。
t
1
图 2 图1
2.栈的存储与操作(称为栈顶指针)由于栈是一个特殊的表,可以用一维数组来实现栈。
同时设立指针t 来指示栈顶元素的当前位置。
为最早入s[1]将栈底固定在数组的底部,我们用一个
数组s[1..m]来表示一个栈时,即时,表示这个栈为一个空栈。
t=0(下标增大的方向)扩展。
当
栈的元素,并让栈向数组上方时,表示这个栈已满。
当t=m 可以用下列方式定义栈:const
; m=栈表目数的上限type
} stack=array[1..m] of stype; {栈的数据类型var
s:stack;
}
t:integer; {栈顶指针进栈、出栈操作的过程和函数(假设栈元素的数据类型为整型):)
(1)进栈过程(push时,则给出溢出信息,作出错处理(进栈前首先检查栈是否已满,满则溢≥
①若tm 出;不满则作②);;(栈指针加1,指向进栈地址)②置t=t+1 为新进栈的元素);xt)=x ③S(,结束(procedure push(var s:stack; x:integer;var t:integer);
begin
if t=m then writeln('overflow')
else
begin
t:=t+1;s[t]:=x;
end
end;
(2)退栈函数(pop)空则下溢;≤0,则给出下溢信息,作出错处理(退栈前先检查是否已为空栈,①若t 不空则作②); x);②x=s(t),(退栈后的元素赋给 t=t-1,结束(栈指针减1,
指向栈顶)。
③function pop(var s:stack;var t:integer):integer;
begin
if t=0 then writeln('underflow')
else
begin
pop:=s[t];t:=t-1;
end
end;
读栈顶元素函数(top)(3)function top(var s:stack; t:integer):integer;
begin
if t=0 then writeln('underflow')
else
top:=s[t];
end;
3栈的应用举例依次入栈,以下出栈序列不可能出现的初始状态为空,元素a,b,c,d,e,f,g【例10-4】.设栈S )。
的是(
C.a,e,d,c,b,f,g B.b,c,a,f,e,g,d A.a,b,c,e,d,f,g
E.g,e,f,d,c,b,a
D.d,c,f,e,b,a,g
,每个元素依次A题解:此题可以采用模拟的方法,依次判断各个选项是否能出现。
如出栈,a 进栈,然后b出栈,c进栈后出栈,进栈然后出栈,即得到此序列。
再来看B,a,b不能进栈后出栈,gd出栈,可以满足。
依此类推,发现只有E,e,f进栈,f,e出栈,d 满足,答案为E。
共五个车厢。
其中有一个无穷大的的栈S,在栈的右边排列着1,2,3,4,5.如下图,】10-5【例3也可以进入栈S让后面的车厢通过。
现已知第一个到达出口的是每个车厢可以向左行走, 号车厢,请
写出所有可能的到达出口的车厢排列总数。
5 4 3 2 1 ←出口←↓S
,4,出栈,此时栈中有元素进栈,然后,题解:首先必是12,3312,未进栈元素有 4我们可以讨论,如下:5的出栈顺序,之前出栈,一定在由于。
5我们可以分情况讨论,21四个数字的一个54(1)4先出栈:此时相当于,不经过栈直接到出口。
相当于42,,,514 5排在前,1排在排列,24/4=6前,共有种数(种)。
4的出栈顺序必连续,有以下三种排列:5和4先出栈:此时(2)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;
const
n=30;
type
stack=array[1..n] of integer;
var
s:stack;
a:string;
t,i,j,k,q:integer;
procedure push(var s:stack; x:integer;var top:integer);
begin
if top=n then writeln('overflow')
else
begin
top:=top+1;s[top]:=x;
end
end;
function pop(var s:stack;var top:integer):integer;
begin
if top=0 then writeln('underflow')
else
begin
pop:=s[top];top:=top-1;
end
end;
begin
i:=1; t:=0;
readln(a);
while a[i]<>'@' do
begin
case a[i] of
'0'..'9' :begin
k:=0;
repeat
k:=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); {取栈首的两个数值相加}
'-' :begin
j:=pop(s,t);
push(s,pop(s,t)-j,t);
end;
'*' : push(s,pop(s,t)*pop(s,t),t); { 取栈首的两个数值相乘}
'/' :begin
j:=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件质量为w,w,...,w的物品和一个最多能装载总质量为T的背包,能否n21从这n件物品中选择若干件物品装入背包,使得被选物品的总质量恰好等于背包所能装载的最大质量,即w+w+...+w=T。
若能,则背包问题有解,否则无解。
iki2i1算法思想
首先将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;
var
i,top:integer;
begin
top:=0;
i:=1;
while (tot>0)and (i<=n)do
begin
if (tot-w[i]>=0)and(i<=n) then begin
top:=top+1;
stack[top]:=i;
tot:=tot-w[i];
end;
if tot=0 then exit(true){正好装满则返回true}
else begin
if (i=n)and(top>0)then{I=n时退栈}
begin
i:=stack[top];dec(top);
tot:=tot+w[i];
if (i=n)and(top>0) then
begin{如退栈后I=n,即退栈的元素是最后一个,则需再次退栈,因为此时已无法选择下一个物品}
i:=stack[top];
dec(top);
tot:=tot+w[i];
end;
end;
inc(i);
end;
end;
exit(false);
end;
begin
readln(t,n);
for i:=1 to n do read(w[i]); if knap(t) then writeln('Yes') else writeln('No');
end.。