指针与链表(2)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
练习
1、围绕着山顶有10 个洞,一只兔子和一只狐狸各住一个洞,狐 狸总想吃掉兔子。一天兔子对狐狸说,你想吃我有一个条件,第 一次隔一个洞找我,第二次隔两个洞找我,以后依次类推,次数 不限。若能找到我,你就可以饱餐一顿,在没找到我之前不能停 止。狐狸一想只有10 个洞,寻找的次数又不限,哪有找不到的道 理,就答应了条件。结果就是没找着。现请你编写一程序,假定 狐狸找了1000 次,兔子躲在哪个洞里才安全。 2、输入一串大写字母,用这些字母建立一个指针链表,然后输出 这个链表。链表中可能有一些重复的字母,将重复的多余字母从 链表中删除,只留下第1个,输出链表。再将剩余链表中的字符 按ASCII码升序重排,然后输出该链表。 例如:输入:DSDFRSSDFGDKAHHAUJDJG 输出:DSDFRSSDFGDKAHHAUJDJG DSFRGKAHUJ ADFGHJKRSU
五、循环链表
1、单向循环链表:最后一个结点的指针指向头结点。如下图:
2、双向循环链表:最后一个结点的后继指针指向头结点,且头 结点的前趋指针指向最后一个结点。如下图:
3、循环链表的应用举例 、循环链
例2、约瑟夫问题 【问题描述】 有n 只猴子,按顺时针方向围成一圈(开始时编号为1,2,……,n), 选大王。从第1号猴子开始报数1,2,3,……,数到m号时该猴子退出 到圈外,如此报数直到圈内只剩下一只猴子时,此猴便是大王。你的任 务是从键盘读入n,m,程序判断输出最后的大王是几号? 如输入:13 5 输出:6 换个问法: n 只猴子围成一个圈,按顺时针方向报数,报到m的出圈, 直到剩下一只猴子结束。输出猴子依次出圈的序号。 【算法分析】 很明显这是一个单向循环链表。数据域为猴子的编号,指针域为下一个 猴子的地址。从第1 个猴子开始一一报数,报数实际上是计数,只要设 一个计数器就可以了。当计数器由1变化到m 时,删除该结点,从下一 个结点开始继续计数(计数器回1 或者用求余运算)。直到链表中只剩 下一个结点。
Procedure insert(head:pointer;i,x:integer);{在双向链表的第i个结点之前插 入X} Var s,p:pointer;j:integer; Begin New(s); S^.data:=x; P:=head; j:=0; while (p^.next<>nil) and (j<i) do begin p:=p^.next; j:=j+1; end; {p指向第i 个结点} if p=nil then writeln(‘no this position!’) else begin {将结点S 插入到结点P之前} s^.pre:=p^.pre; {1、将S 的前趋指向P的前趋} p^.pre:=s; {2、将S 作为P 的新前趋} s^.next:=p; {3、将S的后继指向P} s^.pre^.next:=s; {4、将P 的本来前趋结点的后继指向S} end; End;
q^.next:=head; s:=1;q:=head; repeat p:=q^.next;s:=s+1; if s mod m=0 then begin q^.next:=p^.next; writeln(p^.data:4); dispose(p); end else q:=p until q^.next=q; writeln('the king is:',q^.data) end.
第二章 指针与链表(2)
四、双向链表
每个结点有两个指针域和若干数据域,其中一个指针域指向它的 直接前趋结点,一个指向它的直接后继结点。它的优点是访问、 插入、删除更方便,速度也快了。实质上是以空间换时间。 数据结构的定义: type pointer=^nodetype; nodetype=record data:datatype; pre,next:pointer; {pre指向前趋,next指向后继} end; var head,p,q,r:pointer; 下面给出双向链表的插入和删除过程。
Baidu Nhomakorabea
【参考程序】 program king; type point=^node; node=record data:integer; next:point; end; var m,n,s:integer; p,q,head:point; begin write('input n,m:'); readln(n,m); new(head);q:=head;head^.data:=1; for s:=2 to n do begin new(p);p^.data:=s;q^.next:=p;q:=p; end;
Procedure delete(head:pointer;i:integer);{删除双向链表的第i 个结点} Var p:pointer;j:integer; Begin P:=head; j:=0; while (p^.next<>nil) and (j<i) do begin p:=p^.next; j:=j+1; end; {p指向第i 个结点} if p=nil then writeln(‘no this position!’) else begin {将结点P 删除} p^.pre^next:=p^.next; {1、P 的前趋结点的后继赋值为P的后继} p^.next^.pre:=p^.pre; {2、P 的后继结点的前趋赋值为P的前趋} end; End;