1、2010/3/4,南京树人国际学校09初一信息奥赛,线性链表及应用,单双向链表、有序链表 循环链表、线性表的应用,一、顺序表中结点ai 的存储地址,假设表中每个结点占用c个存储单元,其中开始结点a1的存储地址(简称为基地址)是LOC(a1),那么结点ai的存储地址LOC(ai)为:,LOC(ai)= LOC(a1)+(i-1)*c 1in,二、线性表的链接存储,1、单向线性链表 2、有序链表 3、双向线性链表 4、循环链表,read(ch); head:=nil;while ch# dobeginnew(p); p.data:=ch; p.next:=head; head:=p; read(c
2、h);end;p:=head;,1、用表头插入法建立链表,read(ch); head:=nil; q:=nil; while ch# dobeginnew(p); p.data:=ch; p.next:=nil;if head=nil then begin head:=p; q:=p; endelse beginq.next:=p; q:=p;end; read(ch); end;,2、用表尾插入法建立链表,3、单链表的遍历与输出,PROCEDURE print ( head : point ) ; 带表头指针var p : point ;BEGIN p := headwhile p nil
3、 do begin write ( p.data : 8 ) ; p := p.next ; end ; end; 打印链表的过程 ,4、线性表的查找算法,Procedure search( head :point, ch:char ); Var p:point ; Begin p:=head; while (pnil) and (p.datach) do p:=p.next; if pnil then write(ok) else write(sorry);,插入到头结点: 插入到某一个结点 : 插入到尾部: P.next:=head; P.next:=q.next; r.next :=p;
4、 head:= p; q.next:=p ; r := p ; q:= x ;,5、插入结点的操作,插入算法实现,Procedure insert (var head:point ;ch:char);Var p,q,s:point ;Beginp:=head ; q:=p; new(s) ; s.data:=ch;s.next:=nil;While (pnil) and ( chp.data) do 查找位置beginq:=p ; p:=p.next ;end; 表尾 If p=nil then q.next:=s Else if p=head then,插入表头: Begin S.next
5、:=head; head:=s ; end;else 插入表内begins.next:=q.next ;q.next :=s ;q:=q.next ; end ; end ;,6、单链表的删除,前提:删除p结点后的r结点 表头删除: 表中删除: 表尾删除:,head.next:=p.next; dispose(p);,q.next:=p.next; dispose(p);,q.next:=nil; dispose(p);,删除操作 : 删除头结点 删除某一个结点P:=head ; q.next := p.next ; Head:=head.next; dispose ( p ) ;Dispos
6、e (p);,PROCEDURE dele ( var head :point ; ch:char ) ; var p , q : point ;BEGIN p := head ; q := p ;while ( p.data ch ) and ( p NIL ) do beginq := p ; p := p.next ; end ; 查找所要删除的结点 if p = NIL then writeln ( not found ) else,if p = head then beginp := p.next ;dispose ( q ) ;head := p ;end ;else beginq
7、.next := p.next dispose ( p ) ;p := q.next ;end ; print ( head ) ;end ; 删除一个结点并打印 ,6、建立有序链表,算法:既不能仅用表头插入法,也不能仅用尾插入法输入第一个数,建立结点,三个指针均指向头结点head:=s; p:=s ;q:=p ; 当没有结束时,读入下一个数,建立结点,将该数据与已有的链表的每个结点值比较:while ( s.data p.data ) and ( pnil ) do begin q:=p ; p:=p.next ;end;,插入表头:if p=head then begin s.next:=
8、head; head:=s ;p:=head ;q:=head ;end 否则 : If p=nil then 插入表尾 q.next:=s 否则 插入表中s.next:=q.next ;q.next :=s ; q:=q.next;,7、循环链表,将表尾的指针指向表头,构成循环链接表 (1) 单链表类型描述type link=node;node=recorddata:integer;next:link;end; var head:link;,循环链表:一种首尾相接的链表。单循环链表在单链表中,将终端结点的指针域nil 改为指向表头结点或开始结点即可。(2)带头结点的单循环链表其作用方便插入和
9、删除,算法与单链表类似 打印循环线性表的过程:从头结点的下一个结点开始输出 写出循环链表的遍历过程,procedure print(head:point);var p:point;beginp:=head.next;while phead dobeginwrite(p.da:5);p:=p.next;end; end;,例题1 建立一个若干个学生姓名的循环链接表,并输出,完成以下功能: (1)建立按字典顺序排列的顺序链表,并输出 (2)输入一个学生姓名,若该学生姓名在链表中,则删除该结点,若不在链接表中,则插入该学生姓名,并使其仍然有序。 (3)要有判断链表为空的功能,问题分析: (1)建立循
10、环链表的过程,其实质是不断插入结点的过程,所以首先建立一个头结点,不断插入结点。 (2)在插入结点的过程中,需要判断插入结点的定位问题。总是从表头的下一个结点开始搜索位置。 (3)删除结点的过程,需要寻找删除结点位置(用两个指针变量完成),当找到删除结点,则进行删除否则插入该结点。 (4)打印循环线性表的过程:从头结点的下一个结点开始输出.,program xunhuanlianbiao;type point=stu;stu= recordda:string8 ;link: point ;end;var head,p,q : point ;st1:string8; len,x: integer
11、 ;procedure print( head1:point);var p:point ;beginp:=head1.link ;,while phead1 dobeginwrite(p.da:5);p:=p.link ;end;writeln;end;,procedure inser1( head1:point; st2:string);var p,q,r : point ;beginnew(r);r.da:=st2 ; r.link:=nil ;p:=head1.link ; q:=head1;while (phead1) and (p.dast2) dobeginq:=p; p:=p.l
12、ink ;end;r.link:=q.link ; q.link:=r ; q:=q.link ;end;,procedure dele( head1:point ;st2:string) ;var p,q :point ;beginp:=head1.link ; q:=head1 ;while (p.linkhead1) and (p.dast2) dobeginq:=p; p:=p.link ;end;,if (p.link=p) or ( p.link=head1) thenbegin writeln(not found ) ;inser1( head1,st2);endelse beg
13、inq.link:=p.link ; dispose(p);p:=q.link ;end;end;,beginnew(head);head.da:=#; head.link:= head;p:=head ; readln(st1);while st1# dobegininser1(head,st1);readln(st1);end;print(head);,repeatwrite(please input 1-3 );readln(x);case x of1: begin readln(st1);inser1(head,st1);print(head); end;2: begin readln
14、(st1);dele(head,st1);print(head);end;end;until x=3 ;end.,例题2、猴子选大王,链表实现:教材“数据结构及应用”p 22牵涉知识:建立循环链表,结点计数及删除结点操作,type point=node; node=record data:integer; next:point; end; var m,n,s:integer;p,q,head:point; beginreadln(m,n);new(head);q:=head;head.data:=1;for s:=2 to m dobeginnew(p);p.data:=s;q.next:=p
15、;q:=p;end;q.next:=head;s:=1;q:=head;if n=1 then writeln(m),elsebeginrepeatp:=q.next; s:=s+1;if s mod n=0 thenbeginq.next:=p.next;dispose(p);endelse q:=p; until q.next=q;write(q.data);end; end.,例题3 有两个多项式Y1、Y2编写一个程序,将两个多项式合并同类项。 Y1= 3x7+5x6-4x5-3x2-8x-2 Y2=9x12-6x8-5x7-5x6+x4-8x3+6x2+7x+3 问题分析: (1)多项
16、式合并同类项的方法,系数相加减,指数不变。 (2)多项式的每一项的表示方法可以有两种:用记录数组 : A1.cof ,A1.exp用指针变量表示每一个结点:指针类型指向一个记录,其结构为: 系数域、指数域、指向下一项的地址域,此时选择数据的结构为线性链接表的结构处理该问题比较方便。教材p23(3)建立两个多项式的线性链表(按降幂排列L1,L2) (4)每个线性表有头指针、过渡指针等(head,p,q) (5)分别从两个表头开始,找到第一个插入点(指数最高的那个结点,将该结点插入到表L的第一个结点。指数相同,指数不变,系数相加减指数不同,将指数高的结点先插入表L中,指针向下移最后不论哪个链表插入
17、先结束,则将另一链表,接入尾部。,program exp2_1 ; 用数组完成多项式合并同类项 const max=100 ;type number =record coef :integer ;exp : 0100 ;arr= array1max of number ; var S,R,A :arr ;n,m,j,k , x,y : integer ;,Procedure input ( var h: arr; t:integer ); Var k,j :integer ;BeginFor k:=1 to t doRead(hk.coef, hk.exp); Write(y=);For k:
18、=1 to t do beginIf ( hk.coef0 ) and (k1) then write(+)Write( hk.coef,X, hk.exp, ) ;End; Writeln ;End;,Begin 主程序 Write( input number n, m : );Read(n,m);Writeln;Input( S,n ); input (R,m );x:=1 ; y:=1; k:=1 ;while (x=n) and (y=m) do beginif sx.exp=ry.exp then beginj:=sx.coef+ry.coef,if j0 then begin ak
19、.exp:=sx.exp; ak.coef:=j;x:=x+1 ; y:=y+1 ; k:=k+1 ;endelse begin x:=x+1; y:=y+1 ; end ;end elseif sx.expry.exp then beginak.exp:=sx.exp;ak.coef:=sx.coef ;x:=x+1 ; k:=k+1 ;end,else begin ak.exp:=ry.exp; ak.coef:=ry.coef ;y:=y+1 ; k:=k+1 ;end ;end;while ( x m) do beginak.exp:=sx.exp; ak.coef:=sx.coef
20、;x:=x+1 ; k:=k+1 ;end;,while ( yn) do beginak.exp:=ry.exp; ak.coef:=ry.coef ;y:=y+1 ; k:=k+1 ;end;write( y3=); 输出合并同类项以后的多项式 for j:=1 to k-1 do beginIf ( Aj.coef0 ) and (j1) then write(+);Write(Aj.coef, X, Aj.exp, ) ;end;Writeln ; End.,1、双(向)链表中有两条方向不同的链,即每个结点中除next域存放后继结点地址外,还增加一个指向其直接前趋的指针域front。
21、2、双向链表的结点结构和形式描述 3、双向链表的前插和删除本结点操作,双向链表,双向链表类型定义 Type point= stu ;stu=record num: integer ;Llink, Rlink : point ;end;var head, p,q : point ; x: integer ; procedur print ( head1:point);var p:point ;beginp:=head1 ;,while pnil dobeginwrite(p.num:5);p:=p.rlink ;end;writeln;end;,Procedure create ( var he
22、ad1 : point ) ;var p, q, r : point ; x:integer ;begin p:=head1 ; q:=p ; read( x) ;while x0 do begin new(p) ; p.num:=x; p.Llink :=nil;p.rlink := nil; if head1=nil then being head1:=p ; q:=p; endelse beginq.rlink:= p ; p.Llink :=q ; q:=q.rlink ;end;,read(x);end;r: = p ; print( head1); end; Procedure d
23、ele( var head1 :point ; x : integer) ;var p,q : point ;begin p:=head1 ; q:=p ;while ( p.numx ) and ( pnil) dop:=p.rlink ;if p=head1 then beginhead1:= head1.rlink ;head1.Llink:=nilp:=head1 ;end,else if pnil then begin p.Llink.rlink:=p.rlink;p.rlink.Llink:=p.Llink ; endelse writeln( error) ;print( hea
24、d1);End;begin head:=nil ; create( head );writeln( input dele number x:); read( x); dele( head, x) ;end.,作业 1、将两个有序链表合并为一个有序链表。表head1: (34,56,68,79,90,100)表head2: (12,25,48,74,85) 算法1:建立一个新链表head3,通过大小比较选择将值小的结点复制到head3,当有一个表已处理完毕,则将另一表的顺序部分全部复制到head3中。 如果不建立第三个链表,想一想程序该如何编辑,2、猴子选大王:有n只猴子,按顺时针方向围成一圈选
25、大王。从第一号开始报数1,2,数到m时该猴子退出圈外,再如此报数直到圈内只剩下一个猴子时,此猴子便是大王。由键盘输入n,m,打印出走出圈外的猴子序号及大王序号。 用循环链表完成,3、围绕着山顶有10个洞,一只兔子和一只狐狸各住一个洞,狐狸总想吃掉兔子。一天兔子对狐狸说,你想吃我有一个条件,第一次隔一个洞找我,第二次隔两个洞找我,以后依此类推,次数不限。若能找到我,你就可以饱餐一顿,在没找到我之前不能停止。狐狸一想只有10个洞,寻找的次数又不限,哪有找不到的道理,就答应了条件。结果就是没找着。假定狐狸找了1000次,兔子躲在那个洞里最安全。,4、有一个班的战士,由11人组成,其中6名是老战士,5
26、名新战士。现在必需单线纵向排列穿过敌人的一道封锁线,并且第一、二人越过后,第三人要返回报告情况,然后该队员编排到队伍的末尾。接着第四、第五人越过,第六人返回报告并排到末尾。依次类推,最后三人一起顺次过去。当越过封锁线后,队伍便形成老、新交替的形式。编程求穿越前队伍的排列情况(O为老战士,X为新战士),本题算法与多项式加法相同,只需要定义一个指针变量,指向一个具有两个域的记录:数据域和地址域。type point =numnum=recordn: integer ;link:point ;end;var head1, head2, head3 , p, q :point (1) 定义一个过程建立线性链接表crete(2) 两次调用过程crete分别由head1 , head2指向(3) 循环比较两个链表的第i个数将较小的数据插入到hrad3所指向的链表。,(4) 将剩余一个链表的数据链接到head3链表中。(5) 输出合并后的链表。,战士穿越封锁线:最后目标状态:o x o x o x o x o x o,