p33链接的栈和队列
一、链栈的定义与运算
链栈(即链接堆栈)是栈的链接存储表示,或者说它是只允许在表头进行插入和删除运算的单链表,此时单链表的表头指针叫做栈顶指针。一个链栈的示意图如下图所示,其中HS表示栈顶指针。设HS的类型为linklist(指针类型),数据元素x的类型为elemtype,则在以HS为栈顶指针的链栈中,进行栈的各种运算的算法如下:
1、进栈算法
算法步骤为:
push(HS,x)
new(p)
p^.data:=x
p^.next:=HS
HS:=p
2、出栈算法
假定以函数的形式写出,则算法步骤为:
(1)检查HS是否为空,若为空则进行“下溢”错误处理;
(2)将栈顶结点的值赋给函数名,并将栈顶指针暂存p,以便回收栈顶结点;
(3)删除栈顶结点;
(4)回收p^结点(即原栈顶结点)。
算法描述为:
pop(HS):elemtype;
if HS=nil then error(‘underflow’)
pop:=HS^.data
p:=HS
HS:=HS^.next
dispose(p)
3、读取栈顶元素的算法
此算法很简单,若不考虑栈空的情况,只要取出HS^.data的值即可。
4、置栈空算法
若不考虑回收结点,则只要将HS置空即可。若考虑回收链栈中的所有结点,则算法如下:
setnull(HS);
while HS<>nil do
p:=HS
HS:=HS^.next
dispose(p)
5、判断一个栈是否为空的算法
此算法很简单,只要当HS=nil时返回“真”值,否则返回“假”值即可。
二、链队的定义与运算
链队(即链接队列)是队列的链接存储表示,或者说它是只允许在表尾进行插入和表头进行删除的单链表。一个链队需要队首和队尾两个指针,其中队首指针f指向单链表的表头,队尾指针r指向单链表的表尾。一个链队的示意图如下图所示。
设f和r的类型为linklist(指针类型),则描述f和r的结点类型可以定义为:
type
linkqueue=record
f,r:linklist
end;
设HQ为具有linkqueue类型的一个参数,它表示一个链队,x为具elemtype类型的一个参数,在HQ链队中进行插入、删除和置空队运算的算法如下:
1、 插入算法
(1)、为待入队元素x分配一个结点p^,并把x赋给p^的值域,nil赋给p^结点的指针域;
(2)若链队为空(即HQ.f和HQ.r均为空,检查时判任一个为空即可),则表明待插入的p^结点既是队首结点也是队尾结点,应同时修改队首指针和队尾指针,使之指向p^结点,否则把p^结点插入队尾,并使队尾指针指向p^结点。
算法描述为:
insert(HQ,x)
new(p)
p^.data:=x
p^.next:=nil
if HQ.r=nil
then
HQ.f:=p
HQ.r:=p
else
HQ.r^.next:=p
HQ.r:=p
2、删除算法
算法步骤为:
(1) 若链队为空,则进行“下溢”错误处理;
(2) 把队列首结点的值赋给变参x;
(3) 把队首指针暂存指针变量p,以便回收该结点;
(4) 删除队首结点,即若链队中只有一个结点(即HQ.f=HQ.r),则应同时把HQ.f和HQ.r置为空,否则只修改队首指针,使之指向下一个结点;
(5) 回收原队首结点(即p^结点)。
算法描述为:
delete(HQ,x)
if HQ.f=nil then writeln(‘underflow’)
x:=HQ.f^.data
p:=HQ.f
if HQ.f=HQ.r
then
HQ.f:=nil
HQ.r:=nil
else
HQ.f:=HQ.f^.next
dispose(p)
3、置链队为空的算法
此算法很简单,只要把队首和队尾指针置空即可。
setnull(HQ)
HQ.f:=nil
HQ.r:=nil
不过这样队列中的所有动态结点没有回收,大量浪费了空间,因此可以进行如下改进:
setnull(HQ)
p:=HQ.f
while p<>HQ.r do
q:=p^.next
dispose(p)
p:=q
dispose(p)
HQ.f:=nil
HQ.r:=nil