在趣谈数据结构(一)中,我们谈了"栈"的应用,下面我给出一道问题,大家看看能否用栈的知识来解决?
问题:化学中原子的表示是由一个大写字母或一个大写字母加一个小写字母来表示的。原子团是由原子或更小的原子团参与构成的,原子团的表达式是由左、右圆括号括起来的,NH4原子团的表达式为(NH4)。但当原子团只出现一次,则原子团表达式两端的圆括号可以省略不写。分子是由原子组成,分子式是原子式的组合。例如NH4和co3是两种不同的原子团,碳酸铵分子中有两个NH4原子团和一个co3原子团,故该分子的分子式可以书写成两种形式:(NH4)2CO3、(NH4)2(CO3)。
分子量就是分子的质量,是构成该分子的所有的原子(包括构成该分子的原子团中的各个原子)的质量总和。 例如N的原子量为14,H的原子量为1,C的原子量为12,O的原子量16,因此(NH4)2CO3的分子量为(14+l*4)*2+12+16*3=96。
现已知各原子的原子量,求出给定的各个分子式所对应的分子量。
这一讲,我们就来谈谈"栈"。
队列是限定在一端进行插入,另一端进行删除和特殊线性表。正象排列买东西,排在前面的人买完东西后离开队伍(删除),而后来的人总是排在队伍未尾(插入)。通常把队列的删除和插入分别称为出队和入队。允许出队的一端称为队头,允许入队的一端称为队尾。所有需要进队的数据项,只能从队尾进入,队列中的数据项只能从队头离去。由于总是先入队的元素先出队(先排队的人先买完东西),这种表也称为先进先表(FIFO)表。
队列可以用数组Q[1…m]来存储,数组的上界m即是队列所容许的最大容量。在队列的运算中需设两个指针:
head:队头指针,指向实际队头元素的前一个位置
tall:队尾指针,指向实际队尾元素所在的位置
一般情况下,两个指针的初值设为0,这时队列为空,没有元素。图1 ( a)画出了一个由6个元素构成的队列,数组定义Q[1…10]。
Q(i) i=3,4,5,6,7,8
头指针head=2,尾指针tail=8。队列中拥有的元素个数为:L=tail-head
现要让排头的元素出队,则需将头指针加1。即head=head+1
这时头指针向上移动一个位置,指向Q(3),表示Q(3)已出队。见图1 (b)。
如果想让一个新元素入队,则需尾指针向上移动一个位置。即tail=tail+1
这时Q(9)入队,见图1 (c)。
当队尾已经处理在最上面时,即tail=10,见图1 (d),如果还要执行入队操作,则要发生"上溢",但实际上队列中还有三个空位置,所以这种溢出称为"假溢出"。

克服假溢出的方法有两种。一种是将队列中的所有元素均向低地址区移动,显然这种方法是很浪费时间的;另一种方法是将数组存储区看成是一个首尾相接的环形区域。当存放到n地址后,下一个地址就"翻转"为1。在结构上采用这种技巧来存储的队列称为循环队列,见图2

循环队的入队算法如下:
1、tail=tail+1;
2、若tail=n+1,则tail=1;
3、若head=tail尾指针与头指针重合了,表示元素已装满队列, 则作上溢出错处理;
4、否则,Q(tail)=X,结束(X为新入出元素)。
队列和栈一样,有着非常广泛的应用。
考虑一个分时系统,如果一台计算机联有四个终端,即允许四个用户同时使用这一台计算机。那么, 计算机系统必须设立一个队列, 用以管理各终端用户使用CPU的请求。当某个用户要求使用CPU时,相应的终端代号就入队(插入队尾),而队头的终端用户则是CPU当前服务的对象。我们考虑最简单的情况,
对于当前用户(队头),系统每次分配一个为时间片的时间间隔,在一个时间片内,如果当前用户的作业没有结束,则该终端用户的代号出队后重新入队,插入队尾,等待下一次CPU服务。如果某个用户的作业运行结束,则先退出,出队后不再入队,
整个运行过程就是各终端代号不断地入队、出队,CPU 轮流地为n(n≤4)个终端用户服务。由于计算机的运行速度极快,所以,对于每个终端用户来说,似乎计算机是单独在为其服务。
和线性表一样,栈和队可以采用链表存储结构,当要实现多个栈共享内存或多个队共享内存时,选择链式分配结构则更为合适。
例1 求两个一元多项式的和。输入多项式方式为,多项式项数,每项系数和指数,按指数从大到小的顺序输入。
分析
多项式的算术运算是表处理的一个经典问题。建立两张表a、b分别存放两个多项式的内容,建立表指针ta、tb,指向表a和表b的元素,根据表a、b元素中的指数大小合并输出。
1、比较ta、tb指向元素的大小,若ta的指数大于tb的指数,输出ta元素,改变指针ta;
2、若ta的指数小于tb的指数,输出tb元素,改变指针tb;
3、若ta的指数等于tb的指数,ta、tb元素的系数相加输出,同时改变指针ta和tb;
4、若有一表取空,则输出另一表剩余的内容。
源程序一:多项式相加的顺序表实现
program ex11_5a;
type
node=record
zhi,xi:integer;
end;
ar=array[1..1000] of node;
var
a,b:ar;
ta,tb,n:integer;
begin
write('One : '); readln(n);{输入第一个多项式的系数和指数}
for ta:=n downto 1 do readln(a[ta].xi,a[ta].zhi);
ta:=n;
write('Two : '); readln(n);{输入第二个多项式的系数和指数}
for tb:=n downto 1 do readln(b[tb].xi,b[tb].zhi);
tb:=n;
write('Result is ');
while (ta>0) and (tb>0) do {当两个表均不空时}
begin {比较两表指针指向的项指数,输出指数小的项系数和指数, 同时改变该表指针}
if a[ta].zhi>b[tb].zhi then
begin
if a[ta].xi<0 then write(#8' '#8);
write(a[ta].xi,'x',a[ta].zhi,'+');
dec(ta);
end
else
if a[ta].zhi
begin
if b[tb].xi<0 then write(#8' '#8);
write(b[tb].xi,'x',b[tb].zhi,'+');
dec(tb);
end
else
begin {若两表指针指向的项指数相等,则两系数相加输出, 两表指针同时改变}
if b[tb].xi+a[ta].xi<>0 then
begin
if b[tb].xi+a[ta].xi<0 then write(#8' '#8);
write(b[tb].xi+a[ta].xi,'x',b[tb].zhi,'+');
end;
dec(ta);
dec(tb);
end;
end;
while ta>0 do {若有一表空,则输出另一表的剩余项}
begin
if a[ta].xi<0 then write(#8' '#8);
write(a[ta].xi,'x',a[ta].zhi,'+');
dec(ta);
end;
while tb>0 do
begin
if b[tb].xi<0 then write(#8' '#8);
write(b[tb].xi,'x',b[tb].zhi,'+');
dec(tb);
end;
writeln(#8' '#8);
readln;
end.
源程序二:多项式相加的链表实现
program ex11_5b;
type
link=^node;
node=record
zhi,xi:integer;
nxt:link;
end;
var
a,b:link;
n:integer;
procedure createfifo(var c:link);{建立多项式系数、指数链表}
var
p:link;
i:integer;
begin
new(p);
readln(p^.xi,p^.zhi);
c:=p;
for i:=1 to n-1 do
begin
new(p^.nxt);p:=p^.nxt;readln(p^.xi,p^.zhi);
end;
p^.nxt:=nil;
end;
begin
write('One : '); readln(n); createfifo(a);
write('Two : '); readln(n); createfifo(b);
write('Result is ');
while (a<>nil) and (b<>nil) do
begin
if a^.zhi>b^.zhi then
begin
if a^.xi<0 then write(#8' '#8);
write(a^.xi,'x',a^.zhi,'+');
a:=a^.nxt;
end
else
if a^.zhi
begin
if b^.xi<0 then write(#8' '#8);
write(b^.xi,'x',b^.zhi,'+');
b:=b^.nxt;
end
else
begin
if b^.xi+a^.xi<>0 then
begin
if b^.xi+a^.xi<0 then write(#8' '#8);
write(b^.xi+a^.xi,'x',b^.zhi,'+');
end;
b:=b^.nxt;
a:=a^.nxt;
end;
end;
while a<>nil do
begin
if a^.xi<0 then write(#8' '#8);
write(a^.xi,'x',a^.zhi,'+');
a:=a^.nxt;
end;
while b<>nil do
begin
if b^.xi<0 then write(#8' '#8);
write(b^.xi,'x',b^.zhi,'+');
b:=b^.nxt;
end;
writeln(#8' '#8);
readln;
end.
欢迎大家参加到趣谈数据结构中来。EMAIL地址为:FZYZCY@YEAH.NET或FZYZCY@163.COM