链表1
一、线性链表的概念
先让我们看下面的说明部分
type
point=^node;
node=record
data:integer;
next:point;
end;
var p,q:point;
细心的同学可以发现:指针变量有p和q两个,其基类型为node,node是一个自定义记录类型,有两个域:一个域名为data,类型为整型,另一个域名为next,类型为point型,意思是可以存放另一个node类型存储单元的地址。这里对类型的说明使用了递归的方法。
假设在程序段中出现(如图 10-7所示):
new(p);new(q); {申请两个存储单元}
p^.data:=120;p^.next:=q;{确定指针变量p所指的存储单元的data域的值为120,将变量q所指的存储单元地址赋给p的next域中}
通过上述方法我们就可以将表面上独立的两个存储单元通过指针域连接在一起。依此类推,如果有多个存储单元通过类似的方法进行连接的话,就形成了一个“链”,链中的每一个单元称为“链”中的一个“结点”。一般的,把若干个结点按某一规定的顺序,通过指针域接在一起形成的链,我们称为线性链表。其结构图如下图 10-8所示:
需要说明的是上图中每一个结点顶端的数字表示的是该存储单元的地址值,链表中的第一个结点称为表头,最后一个元素称为表尾。指向链表头的指针称为头指针(head),表尾结点的指针域值为空(NIL)。从上图中我们可以看出,链表的特点是除第一个结点和最后一个结点外,每一个结点中都有一个直接的前趋结点和一个直接的后继结点。相邻结点的地址是互不连续的,它们靠指针域将相互间的关系连接起来。
链表的基本操作主要有链表的建立、链表的遍历、链表中结点数据的访问、向链表中插入一个结点、从链表中删除一个结点等,这些操作无一不是从指针域入手加以考虑的。
可见,链表是动态数据结构的最基本形式。它是一个结点的序列,其中的每一个结点被链接到它前面的结点上。在链表中每个结点有两个部分:一个是数据部分(可以是一个或多个),另一个是指向下一个结点的指针域,有一个头指针指向链表的表头结点,表尾结点的指针域应为NIL1表示表的结束。
二、线性链表的建立
一个线性链表的建立过程简单地说分三步:
申请新结点;
在结点的数据域填相应数据,在指针域填NIL;
将结点链接到表中某一位置。
如果组成链表的各结点只有一个用来指向下一结点的域,则我们称这样的链表为单向链表(即只能从前一结点边接到后一结点,而后一结点不能边接到前一结点)。单向链表的结构示意图,如图10-8所示。
现在我们通过前面定义这样的这个指针结构来看看单向链表的一些相关操作:
type
point=^node;
node=record
data:integer;
next:point;
end;
var head,last,next:point;
x:integer;
begin
readln(x);
new(head);
head^.data:=x;
last:=head;
read(x);
while x>=0 do
begin
new(next);
next^.data:=x;
last^.next:=next;
last:=next;
read(x)
end;
last^.next:=nil
end.
例1 输入一个正整数序列,遇负数时停止,以此建立一个按输入顺序排列的线性链表。
所需的数据类型说明:
type
point=^node;
node=record
data:integer;
next:point;
end;
变量说明为:
var
p,q,head:point;{p用于存放新申请的结点的地址,q用于存放目前已建立链表的尾结点的地址}
x:integer;
算法如下:
从空表开始,头指针置NIL;
读入一个数;
while读入的数为正整数do
begin
if 要填数据的结点为头结点
then begin
申请新结点;
填新结点数据域,指针域置NIl;
设置头、尾指针都指向新结点;
end;
else begin
申请新结点;
将读入的数送入新结点的数据域,指针域置NIL;
将新结点链接到已有的表的表尾;
尾指针后移一个结点,调整尾指针指向新的表尾(为连接下一个新结点作准备);
end;
读下一个数;
end;
参考程序:
head:=NIL;
read(x);
while x>=0 do begin
if head=NIL
then begin new(p);p^.data:=x;p^.next:=NIL;q:=p;head:=p end
else begin
new(p);
p^.data:=x;p^.next:=NIL;q^.next:=p;q:=p;
end;
read(x)
end;{while}
三、线性链表的遍历与输出
一个链表的遍历输出过程就是从表头结点开始按链接的顺序依次访问至表尾的过程。解决方法如下:
设临时工作变量p指针指向链表的头结点(头结点的地址不能丢失和改变,否则会丢失整个链表);
p:=head;
while p<>nil do
begin
输出p所指结点(当前结点)的数据值;
p移向后一个结点;
end;
while p<>nil do
beign
write(p^.data:8);p:=p^.next
end;
例2.将两个有序单链表A、B中数据域值相同的结点组成一个新链表。
问题分析:该问题实际上就是如何建立新链表,只不过链表中结点的数据域是通过两个有序链表的数据域进行比较得到的。
参考程序:
program aa;
type
point=^node;
node=record
data:integer;
next:point;
end;
var
head1,head2,head3:point;
procedure creat(var head:point);
var
p,q:point;
x:integer;
begin
head:=nil;read(x);
while x>=0 do
begin
if head=nil then
begin
new(p);head:=p;p^.data:=x;p^.next:=nil;q:=p
end
else begin
new(p);q^.next:=p;p^.data:=x;q:=p
end;
read(x)
end;
q^.next:=nil
end;
procedure same(head1,head2:point;var head3:point);
var
p1,p2,p,q:point;
begin
p1:=head1;p2:=head2;head3:=nil;q:=head3;
while p1<>nil do
begin
while p2<>nil do
begin
if p1^.data=p2^.data then
if head3=nil then begin
new(p);head3:=p;
p^.data:=p1^.data;
q:=p
end
else begin
new(p);q^.next:=p;
p^.data:=p1^.data;
q:=p
end;
p2:=p2^.next
end;
p2:=head2;p1:=p1^.next
end;
q^.next:=nil
end;
procedure print(head:point);
var
p:point;
begin
p:=head;
while p<>nil do begin
write(p^.data:6);
p:=p^.next
end;
writeln
end;
begin
write(‘input the first link:’);
creat(head1); print(head1);
write(‘input the second link:’);
creat(head2); print(head2);
same(head1,head2,head3);
if head3=nil then writeln(‘no solution!’) else print(head3)
end.
测试运行结果如下:
输入:input the first link:2 3 6 8 9 7 -1
input the second link:3 5 9 -1
输出:3 9
输入:input the first link:2 3 5 7 -1
input the second link:4 6 8 -1
输出:no solution!
四、线性链表的查找
对于链表的查找是指在链表中找出符合条件的结点。查找的过程如下:
设临时工作变量p指针指向链表的头结点;
while (未找到) and (未到表尾) do
if 找到 then 退出循环
else p 移向下一个结点;
if 到了表尾 then 输出“未找到” else (找到)对p所指结点进行相应的处理。
为了能够表示出是否找到结点,在程序段中用到了一个布尔型的变量found,若找到,found的值为true,若找不到found的值为false。
参考程序段:
write(‘input a data for look for:’);
readln(x);
p:=head;
found:=false;
while (p<>nil) and not (found) do
begin
if x=p^.data then found:=true
else p:=p^.next;
end;
if found then writeln(p^.data)
else writeln(‘no found’);
习题
1.完善程序
设有一非空链表,表头结点指针为head,下面的程序是找出链表中所有结点数据域的最大值。
program aa;
type point=^node;
node=record
data:integer;
link:point
end;
var temp:integer;
p,head:point;
begin
…… {建立一非空链表}
temp:=0;p:=head;
while (p<>nil ) do
begin
if (p^.data>temp ) then temp:=p^.data;
(p:=p^.next )
end;
writeln(‘the max number is: ’,temp)
end.
2. 编一过程打印链表head中的所有整数,5个一行
分析:设置一个工作指针P,从头结点顺次移到尾结点,每移一次打印一个数据。
过程如下:
procedure print(head:pointer);
var p:pointer; n:integer;
begin
n:=0;p:=head;
while p<>nil do
begin
write(p^.data:8);n:=n+1;
if n mod 5=0 then writeln;
p:=p^.next;
end;
writeln;
end;
完整程序参考:
program aa;
type point=^node;
node=record
data:real;
next:point;
end;
var
p,q,head:point;
x:real; i:integer;
begin
read(x);
head:=nil;
while x>=0 do
begin
if head=nil then
begin
new(p);
p^.data:=x;
p^.next:=nil;
q:=p;
head:=p;
end else
begin
new(p);
p^.data:=x;
p^.next:=nil;
q^.next:=p;
q:=p;
end;
read(x);
end;
p:=head;
while p<>nil do
begin
write(p^.data,' ');
p:=p^.next;
end;
p:=head;
while p<>nil do
begin
if p^.data=(p^.data div 1) then
begin
write(p^.data:0:0,' ');
i:=i+1;
if i mod 5=0 then writeln;
end;
p:=p^.next;
end;
end.
3. 编写一个过程,将读入的一串整数存入链表, 并统计整数的个数
分析:过程的输入为一串整数,这在执行部分用读语句完成。过程的输出有两个:一是链表的头指针,一是整数的个数,这两个输出可以用变量形参来实现。
由于不知道整数的个数,我们用一个特殊的9999作为结束标记。
过程如下:
procedure creat(var h:pointer;var n:integer);
var p,q:pointer;x:integer;
begin
n:=0;h:=nil; read(x);
while x<>9999 do
begin
New(p);
n:=n+1;p^.data:=x;
if n=1 then h:=p
else q^.next:=p;
q:=p;
read(x)
end;
if h<>nil then q^.next:=nil;
Dispose(p);
end;
完整程序参考:
program aa;{Input a data to delete.}
type point=^node;
node=record
data:integer;
next:point;
end;
var
p,q,head:point;
a,x,i:integer;
f:boolean;
procedure creat;
var p,q,head:point;
i:integer;
begin
read(x);
head:=nil;
i:=0;
while x>=0 do
begin
if head=nil then
begin
new(p);
p^.data:=x;
p^.next:=nil;
q:=p;
head:=p;
i:=i+1;
end else
begin
new(p);
p^.data:=x;
p^.next:=nil;
q^.next:=p;
q:=p;
i:=i+1;
end;
read(x);
end;
p:=head;
while p<>nil do
begin
write(p^.data,' ');
p:=p^.next;
五、线性链表结点的插入
由于线性链表结点物理地址的非连续性,对于结点的插入事实上就是改变线性链表中某结点的后继指针的值。根据插入位置的不同,我们分三种不同的情况进行分析:表头插入,表中插入和表尾插入。
表头插入
算法描述
申请一新结点newpoint
输入的数赋给newpoint的数据域;
将head的值赋给newpoint的指针域;
将newpoint结点的地址赋给head。
参考程序段:
new(newpoint);readln(x);newpoint^.data:=x;
newpoint^.next:=head;head:=newpoint;{这两步操作顺序不能颠倒,请分析为什么?}
表中插入
算法描述
申请一新结点newpoint;
将数值赋值给newpoint的数据域;
将新结点newpoint的指针域赋值为插入点前一个结点(用p表示)的指针域;
将newpoint的地址赋值给插入点前一个结点(用p表示)的指针域。
参考程序段:
new(newpoint);readln(x);newpoint^.data:=x;
newpoint^.next:=p^.next;p^.next:=newpoint;{这两步操作顺序不能颠倒,请分析为什么?}
表尾插入
算法描述
申请一新结点newpoint;
将数值赋值给newpoint的数据域,将NIL赋值给新结点newpoint的指针域;
将newpoint的地址赋值给已建立的链表的尾结点(用q表示)的指针域。
参考程序段:
new(newpoint);readln(x);newpoint^.data:=x;newpoint^.next:=NIL;
q^.next:=newpoint;
例3. 输入一个正整数序列,遇负数时停止,并按输入顺序反向输出。
问题分析:由于线性链表进行数据访问时只能从表头结点开始,根据问题要求可知,在线性链表建立时必须采用插入到表首的方法进行建立。
解决该问题需用的数据类型与上例相同,不再重复。
算法描述
表头指针置为NIL;
输入一个数;
while 读入的数为正整数 do
begin
申请一新结点;
将读入的数送入新结点的数据域;
将原表头指针赋给新结点的指针域;
将新结点的地址赋给表头指针;
读入下一个值;
end;
顺序输出各结点的数据值。
参考程序:
program aa;
type
point=^node;
node=record
data:integer;
next:point;
end;
var p,q,head:point;
x:integer;
begin
head:=nil;readln(x);
while x>=0 do
begin
new(p);p^.data:=x;
p^.next:=head;
head:=p;
readln(x);
end;
p:=head;
while p<> nil do
begin
write(p^.data:8);
p:=p^.next
end;
writeln;
end.
例4. 设链表head中的数据是按从小到大顺序存放的,在链表中插入一个数,使链表仍有序。
分析:显然,应分两步:查找、插入。设po指向要插入的结点,若仅知道po应插在p之前(作为p的前趋结点)是无法插入的,应同时知道p的前趋结点地址q。
当然,如果插在链表原头结点这前或原链表为空表或插在原尾结点之后,则插入时又必须作特殊处理。
过程如下:
procedure inserting(var head:pointer;x:integer);
var po,p,q:pointer;
begin
new(po); po ^.data:=x;
p:=head;
if head=nil{原表为空表}
then begin
head:=po;po^.next:=nil;
end
else begin
while (p^.data<x)and(p^.next<>nil)do
begin
q:=p;p:=p^.next
end;
if p^.data>=x{不是插在原尾结点之后}
then begin
if head=p then head:= po
else q^.next:= po;
po ^.next:=p
end
else begin
po ^.next:= po;
po ^.next:=nil
end;
end;
end;
完整程序参考:
program fdsa;
type pointer=^node;
node=record
data:integer;
next:pointer;
end;
var p,q,head: pointer;x,k,i:integer;
procedure inserting(var head:bo;x:integer);
var po,p,q:pointer;
begin
new(po); po ^.data:=x;
p:=head;
if head=nil
then begin
head:= po; po ^.next:=nil;
end
else begin
while (p^.data<x)and(p^.next<>nil)do
begin
q:=p;p:=p^.next
end;
if p^.data>=x
then begin
if head=p then head:= po
else q^.next:= po;
po ^.next:=p
end
else begin
p^.next:= po;
po ^.next:=nil
end;
end;
end;
begin
read(x);
head:=nil;
while x>=0 do
begin
if head=nil then
begin
new(p);p^.data:=x;p^.next:=nil;head:=p;q:=p;end
else begin
new(p);p^.data:=x;p^.next:=nil;q^.next:=p;q:=p;end;
read(x);
end;
readln;
read(k);
inserting(head,k);
p:=head;
while p<>nil do
begin
write(p^.data,' ');
p:=p^.next;
end;
end.
习题
完善程序
下面的程序是将数组a中存放的n个整数转存到单链表h中.
program aa;
type point=^node;
node=record
data:integer;
next:point;
end;
var
a:array[1..10] of integer;
i:integer;
head:point;
procedure creat( var head:point );
var p,q:point;
i:integer;
begin
new(p);head:=p;
for i:=1 to 10 do
begin
p^.data:=a[i]; q:=p;
new(p);
(q^.next:=p)
end;
(q^.next:=nil)
end;
procedure print(var head:point);
var p:point;
begin
p:=head;
while p<>nil do
begin
write(p^.data:6);p:=p^.next
end
end;
begin
write(‘input an array:’);
for i:=1 to 10 do read(a[i]);
creat(head);
print(head);
end.
六、线性链表结点的删除
线性链表结点的删除相对于插入操作来说,实现起来就简单得多。一般分两步完成:
1.把要删除的结点地址赋给一个临时变量;
2.把要删除的结点的指针域赋给要删除的结点的前一结点的指针域;
最后把将要删除的结点删除,释放存储单元。
在利用程序实现结点删除时,需要用到两个指针变量:变量q表示要删除结点的前一结点的地址,变量p表示要删除的结点的地址。下面的图示分别表示了删除表头结点、删除表中结点和删除表尾结点三种不同的情况。
`
参考程序段:
q:=head;p:=q^.next;head:=p;dispose(q);
参考程序段:
q^.next:=p^.next;dispose(p);
参考程序段:
q^.next:=p^.next;dispose(p); 或者也可以用q^.next:=NIL;dispose(p)
被删除结点所占用的存储空间可以通过语句dispose(p),交还给系统。
因此,对于线性链表中操作总的来说可以分为:线性链表的建立、线性链表的输出、结点的查找、结点的插入和结点的删除。所有这些操作最关键的地方就是在于如何改变结点指针域的值。
掌握线性链表的访问基本方法是,从头结点开始沿线链表方向进行探求,一般用到两个指针型变量:一个用于指向刚查过的结点地址,另一个用于指向下一个待查的结点地址。
结束访问的条件有两 个:一个是结点地址为NIL,另一个是找到了相应的结点。
最容易出现的错误是,当p为NIL时,取p^.data,因为当p是NIL时,p^.data的值是无意义的。
例5.设单链表h中存有若干个非负整数,删除所有值为素数的结点。
问题分析:该问题实际上是解决如何在链表中删除结点。解题的关键有两点:
(1) 沿链表顺序对结点的数据域逐个进行是否为素数的判断;
(2) 删除时要分清是删除链表中的结点还是链表尾的结点。
算法分析:
(1) 根据数据输入的顺序建立链表;
(2) 从表头结点开始沿链表方向对结点的数据域逐个进行是否为素数的判断,删除是素数的结点;
if p 结点数据域为素数 then
if p 结点是表头结点 then 修改表头 else 删除p 结点;
(3) 输出删除后的链表。
画结点链表,有助理解
参考程序:
program aa;
type
point=^node;
node=record
data:integer;
next:point;
end;
var
head1:point;
function sushu(x:integer):boolean;
var
found:boolean;
i:integer;
begin
found:=true;
if (x=0) or (x=1) then found:=false;
if x=2 then found:=true;
for i:=2 to x-1 do
if x mod i=0 then found:=false;
sushu:=found
end;
procedure creat(var head:point);
var
x:integer;
p,q:point;
begin
head:=nil;q:=head;
read(x);
while x>=0 do
begin
if head=nil then
begin
new(p);p^.data:=x;
head:=p;q:=p
end
else
begin
new(p);q^.next:=p;
p^.data:=x;q:=p
end;
read(x)
end;
q^.next:=nil
end;
procedure delete(var head:point);
var
p,q:point;
begin
p:=head;q:=head;
while p<>nil do
begin
if sushu(p^.data)
then if p=head
then begin head:=p^.next;q:=head end
else q^.next:=p^.next
else q:=p;
p:=p^.next
end;
end;
procedure print(head:point);
var
p:point;
begin
p:=head;
if p=nil then
writeln(‘no solution!’) { [sə'lju:ʃən] 解答}
else
while p<>nil do
begin
write(p^.data:6);
p:=p^.next
end;
writeln
end;
begin
write(‘input a link:’);
creat(head1);
delete(head1);
print(head1)
end.
测试运行结果如下:
输入:2 3 6 8 9 7 -1
输出:6 8 9
输入:2 3 5 7 -1
输出:no solution!
输入:4 6 8 9 13 —1
输出:4 6 8 9
例6.在一个有序链表中装有1到100共100个整数。要求任意输入100以内的一个整数,把它从链表中删除。
PROGRAM e1(input,output);
TYPE point=^pp;
pp=record
data:integer;
link:point;
end;
VAR
p1,p2,p3,k:point;
i:integer;
BEGIN
{建立一个1――100的整数的有序链表}
new(p1);
k:=p1;
p1^.data:=1;
for i:=2 to 100 do
begin
new(p2);
p2^.data:=i;
p1^.link:=p2;
p1:=p2;
end;
p2^.link:=nil;
{输入要删除的结点的DATA值}
new(p3);
writeln('input p3');
readln(p3^.data);
P1:=k;p2:=k;
{P2指针查找P3结点}
while p2^.data<p3^.data do
p2:=p2^.link;
{P1指针定位于P3之前}
while p1^.link<>p2 do
p1:=p1^.link;
p1^.link:=p2^.link;
dispose(p3);{将P3结点的空间释放}
{输出修改后的链表}
repeat
write(k^.data,'->');
k:=k^.link;
until k^.data=100;
write(k^.data);
END.
例7.将链表head中值为X的第一个结点删除
分析: 有三种情况存在:头结点的值为X; 除头结点外的某个结点值为X;无值为X的结点。为将前两种情况统一起来, 我们在头结点之前添加一个值不为X的哨兵结点。
算法分两步:查找、删除。
过程如下:
procedure deleting(var head:pointer;x:integer);
var p,q:pointer;
begin
New(p);p^.data:=x-1;p^.next:=head;
head:=p;{以上为添加哨兵结点}
while(x<>p^.data)and(p^.next<>nil) do
begin
q:=p;
p:=p^.next
end;
if x=p^.data{存在值为X的结点}
then q^.next:=p^.next
else writeln('not found!');
head:=head^.next{删除哨兵}
end;
小结:
本题主要是帮助大家掌握链表中结点删除的方法。结点删除的要点在于要分清楚删除的结点是否为表头结点,如果是表头结点,则需要将表头地址进行修改。当然本参考算法不是最好的。解决这一问题还可以直接通过建立链表的方法实现,只是在新建结点时需要对输入的数据进行是否为素数的判断,对满足条件的数据才链接到链表中,相关程序请同学们自行编写。
习题
阅读程序:
1.建立一个有10个结点的链表,最后输出该链表。
PROGRAM E1(INPUT,OUTPUT);
TYPE point=^pp;
pp=record
data:string[5];
link:point;
end;
VAR
p1,p2,k:point;
i:integer;
BEGIN
{产生新结点P1,作为链表的头}
new(p1);
writeln('input data');
readln(p1^.data);
{指针K指向链表头}
k:=p1;
{用循环产生9个新结点,每个结点都接在上一个结点之后}
for i:=1 to 9 do
begin
new(p2);
writeln('input data');
readln(p2^.data);
p1^.link:=p2;
p1:=p2;
end;
{给最后一个结点的LINK域赋空值NIL}
p2^.link:=nil;
{从链表头开始依次输出链表中的DATA域}
while k^.link<>nil do
begin
write(k^.data,'->');
k:=k^.link;
end;
END.
在本程序里,输出链表的过程就是一个链表的遍历。给出一个链表的头结点,依次输出后面每一个结点的内容,指针依次向后走的语句用K:=K↑.LINK 来实现。
2.读入一批数据,遇负数时停止,将读入的正数组成先进先出的链表并输出。
分析:首先应定义指针类型,结点类型和指针变量,读入第一个值,建立首结点,读入第二个值,判断它是否大于零,若是,建立新结点。
PROGRAM fifo(input,output);
{建立先进先出链表}
TYPE
Point=^node;
Node=RECORD
Data:real;
Link:point
END;
VAR
head,last,next:point;
x:real;
BEGIN
{读入第一个值,建立首结点}
read(x);
write(x:6:1);
new(head);
head^.data:=x;
last:=head;
{读入第二个值}
read(x);
write(x:6:1);
WHILE x>=0 DO
BEGIN
{建立新结点}
new(next);
next^.data:=x;
last^.link:=next; {链接到表尾}
last:=next; {指针下移}
read(x); {读入下一个值}
write(x:6:1)
END;
Writeln;
Last^.link:=NIL; {表尾指针域置NIL}
Next:=head;
WHILE next<>NIL DO {输出链表}
BEGIN
Write(next^.data:6:1);
Next:=next^.link
END;
Writeln
END.
3.建立一个有序的整数链表,再将一任意整数插入进链表,使链表仍然有序。
PROGRAM e1(input,output);
TYPE point=^pp;
pp=record
data:integer;
link:point;
end;
VAR
p1,p2,p3,k:point;
BEGIN
{建立一个整数的链表,要求输入的整数依次是有序的,以数9999结束}
new(p1);
writeln('input data');
readln(p1^.data);
k:=p1;
repeat
new(p2);
writeln('input data');
readln(p2^.data);
p1^.link:=p2;
p1:=p2;
until p2^.data=9999;
p2^.link:=nil;{有序链表建立完毕}
writeln('input p3');
readln(p3^.data);
p1:=k;p2:=k;{P1,P2都指向表头}
{P2找到插入点后一个结点}
while p2^.data<p3^.data do
p2:=p2^.link;
{P1找到插入点以前的结点}
while p1^.link<>p2 do
p1:=p1^.link;
{将P3接入P1,P2之间}
p1^.link:=p3;
p3^.link:=p2;
{将整个插入后的链表依次打印出来}
repeat
write(k^.data,'->');
k:=k^.link;
until k^.data=9999;
write(k^.data);
END.
4.建立一个若干整数的链表后(-1结束)再从链表中删除从键盘上输入一个整数的所有结点.(程序)
链表的删除程序如下:
program lianbiao;
type link=^data;
data=record
num:integer;
next:link;
end;
var head,p,tail,r:link;
i,x:integer;
begin
writeln('input lbdata:');
head:=nil;
readln(i);
while i<>-1 do
begin
new(p);
p^.num:=i;
p^.next:=nil;
if head=nil then begin head:=p; tail:=p end
else begin tail^.next:=p; tail:=p end;
readln(i);
end;
write('input delete integer:');
readln(x);
p:=head;
while p<>nil do
begin
if p^.num=x then
if p=head then begin head:=p^.next;p:=head end
else if p^.next<>nil then
begin r^.next:=p^.next ;p:=p^.next end
else
begin r^.next:=nil;p:=nil end
else begin r:=p;p:=p^.next end;
end;
p:=head;
while p<>nil do
begin
write(p^.num:6);
p:=p^.next;
end;
readln;
end.

浙公网安备 33010602011771号