链表Word文档下载推荐.docx
- 文档编号:17903031
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:14
- 大小:102.03KB
链表Word文档下载推荐.docx
《链表Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《链表Word文档下载推荐.docx(14页珍藏版)》请在冰豆网上搜索。
指针类型标识符;
2.申请存储单元{动态申请、空间大小由指针变量的基类型决定}
new(指针变量名);
{PASCAL标准过程}
3.指针变量的赋值
指针变量名:
=NIL;
{初始化,暂时不指向任何存储单元}
如何表示和操作指针变量?
不同于简单变量(如A:
=0;
),PASCAL规定用“指针变量名^”的形式引用指针变量(如P^:
)。
如下图:
4.相同基类型的指针变量之间可以进行相互赋值。
如有下面的程序段,可以画出右边的示意图:
varp1,p2:
^integer;
new(p1);
new(p2);
p1^:
=90;
p2^:
=80;
p1:
=p2;
5.关系运算
如:
ifp1=p2then……
whilep<
>
nildo……
6.释放动态存储单元
dispose(指针变量名);
(二)单链表的结构、建立、输出
由于单链表的每个结点都有一个数据域和一个指针域,所以,每个结点都可以定义成一个记录。
比如,有如下一个单链表,如何定义这种数据结构呢?
typepointer=^nodetype;
nodetype=record
data:
datatype;
next:
pointer;
{嵌套定义}
end;
varhead,p,q,r:
下面给出建立并输出单链表的程序,大家可以把它改成过程用在以后的程序当中。
Programcreat;
integer;
varhead,p,r:
{r指向链表的当前最后一个结点,可以称为尾指针}
x:
begin
writeln('
pleaseinputnum(-1isend):
'
);
read(x);
new(head);
{申请头结点}
head:
=nil;
{头结点初始化}
r:
=head;
whilex<
-1do{读入的数非-1}
begin
new(p);
{则,申请一个新结点}
p^.data:
=x;
p^.next:
r^.next:
=p;
{把新结点链接到前面的链表中,实际上r是p的直接前趋}
{尾指针后移一个}
{最后一个结点的指针域赋空}
readln;
output:
'
{输出}
p:
=head^.next;
{头指针没有数据,只要从第一个结点开始就可以了}
whilep^.next<
nildo
write(p^.data:
4);
=p^.next;
{最后一个结点的数据单独输出,也可以改用REPEAT循环}
end.
{请大家改写这个程序,把链表的实际结点个数存入到头结点中,并输出}
(三)单链表的操作
1.查找“数据域满足一定条件的结点”
p:
=head^next;
while(p^.data<
x)and(p^.next<
nil)dop:
{找到第一个就结束}
ifp^.data=xthen找到了处理else输出不存在;
如果想找到所有满足条件的结点,则修改如下:
whilep^.next<
nildo{一个一个判断}
ifp^.data=xthen找到一个处理一个;
end;
2.取出单链表的第i个结点的数据域
functionget(head:
i:
integer):
varp:
j:
j:
=1;
while(p<
nil)and(j<
i)do
=j+1;
if(p<
nil)and(j=i)thenwriteln(p^.data)
elsewriteln(‘inotexsit!
’);
3.插入一个结点在单链表中去
procedureinsert(head:
x:
integer);
{插入X到第i个元素之前}
varp,s:
=0;
i-1)do{寻找第i-1个结点,插在它的后面}
if(p=nil)or(j>
i-1)thenwriteln(‘nothisposition!
’)
elsebegin{插入}
new(s);
s^.data:
s^.next:
=s;
4.删除单链表中的第i个结点(如下图的“b”结点)
proceduredelete(head:
{删除第i个元素}
while(p^.next<
i-1)do
{p指向第i-1个结点}
if(p^.next=nil)or(j>
elsebegin{删除p的后继结点,假设为s}
s:
=p^.next^.next;
{或p^.next:
=s^.next}
dispose(s);
5.求单链表的实际长度
functionlen(head:
pointer):
varn:
n:
nildo
=n+1;
p:
len:
=n;
(四)双向链表
每个结点有两个指针域和若干数据域,其中一个指针域指向它的前趋结点,一个指向它的后继结点。
它的优点是访问、插入、删除更方便,速度也快了。
但“是以空间换时间”。
数据结构的定义:
pre,next:
{pre指向前趋,next指向后继}
下面给出双向链表的插入和删除过程。
Procedureinsert(head:
i,x:
{在双向链表的第i个结点之前插入X}
Vars,p:
Begin
New(s);
S^.data:
P:
while(p^.next<
{p指向第i个结点}
ifp=nilthenwriteln(‘nothisposition!
elsebegin{将结点S插入到结点P之前}
s^.pre:
=p^.pre;
{将S的前趋指向P的前趋}
p^.pre:
{将S作为P的新前趋}
{将S的后继指向P}
p^.pre^.next:
{将P的本来前趋结点的后继指向S}
End;
Proceduredelete(head:
{删除双向链表的第i个结点}
Varp:
elsebegin{将结点P删除}
p^.pre^next:
{P的前趋结点的后继赋值为P的后继}
p^.next^.pre:
{P的后继结点的前趋赋值为P的前趋}
(五)循环链表
单向循环链表:
最后一个结点的指针指向头结点。
双向循环链表:
最后一个结点的指针指向头结点,且头结点的前趋指向最后一个结点。
循环链表的应用举例:
约瑟夫问题。
[问题描述]
有n只猴子,按顺时针方向围成一圈(开始时编号为1,2,……n),选大王。
从第1号猴子开始报数1,2,3……,数到m号时该猴子退出到圈外,如此报数直到圈内只剩下一只猴子时,此猴便是大王。
你的任务是从键盘读入n,m,程序判断输出最后的大王是几号?
[数据结构和算法分析]
数据结构:
显然是一个单向循环链表。
数据域为猴子的编号,指针域为下一个猴子的地址。
算法:
报数实际上是计数,只要设一个计数器就可以了。
当计数器由0变化到m时,删除该结点,计数器回0继续计数(或者用求余运算)。
直到链表中剩下一个结点。
[参考程序]
programking(input,output);
typepointer=^monkey;
monkey=record
num:
varhead,p,q:
n,m:
procedurecreat(varhead:
n:
{建立一个单向循环链表}
varp,q:
{建立头结点}
p^.num:
q:
{q指向链表的尾结点}
fori:
=2tondo{建立链表}
=i;
q^.next:
{把P结点连接到q的后面}
{建立循环链表}
procedureselectking(varhead:
varm:
i,count:
count:
{指向第一个结点,洋计数1}
{q为p的前趋}
repeat
=q^.next;
count:
=count+1;
ifcountmodm=0thenbegin{该猴子出圈,即删除结点}
dispose(p);
end
elseq:
{指针往后移一个}
untilp^.next=p;
{只剩下一个结点}
begin{main}
write(‘inputmonkeynum:
readln(n);
writeln(‘thebaoshunumber:
readln(m);
creat(head,n);
selectking(head,m);
writeln(‘themoneykingisno.’,head^.num);
readln
[运行测试]
输入:
inputmonkeynum:
13
thebaoshunumber:
5
输出:
themoneykingisno.6
(六)线性表的应用举例
1.链表的归并操作
已知线性表L1和L2中的数据元素按值非递减有序排列,现要求将L1和L2归并成一个新的线性表L3,使L3中的数据元素仍按非递减有序排列。
例如:
L1=(1,3,4,5,8,9,10,11,12),L2=(2,4,6,8),则L3=(1,2,3,4,4,5,6,8,8,9,10,11,12)。
注意:
相同元素照算。
[标准过程]
proceduremerge(h1,h2:
varh3:
pointer);
{将头指针分别为h1,h2的两个单链表归并成一个新的单链表,该链表头指针为h3}
varp1,p2,p3:
{临时用工作指针,一般不能破坏头指针}
p1:
=h1^.next;
p2:
=h2^.next;
h3:
=h1;
{新链表共用第一个链表,简化,也可以另外开辟一个头结点}
p3:
=h3;
while(p1<
nil)and(p2<
nil)do{归并}
ifp1^.data<
=p2^.datathenbegin{将p1结点链接到p3中去}
p3^.next:
=p1;
{指向}
{p3后移}
=p1^.next{p1后移}
elsebegin{将p2结点链接到p3中去}
=p2^.next
ifp1<
nilthenp3^.next:
=p1{将p1中剩下的结点一起链接到p3中}
elsep3^.next:
{将p2中剩下的结点一起链接到p3中}
2.一元多相式的表示和加减运算
在数学上,一个一元n次多项式Pn(x),可以按升幂写成:
Pn(x)=P0+P1X+P2X2+P3X3+……+PnXn
它由n+1个系数唯一确定。
因此,在计算机里,它可以用一个线性表P来表示:
P=(P0,P1,P2,……Pn)
每一项的指数i隐含在系数Pi的序号里。
[任务]
给定一个一元n次多项式Pn(x)和一个一元m次多项式Qm(x),求它们的和与差。
[数据结构]
方法1:
按n,m分别生成n+1和m+1个结点的两个单链表,即不管系数是否为0都生成一个结点。
一个指针域指向后继结点,一个数据域存放系数(不存在的项系数为0)。
浪费了很多空间,尤其是指数很高,而项数很少的情况下,浪费更严重。
方法2:
只生成存在的项,实际多少项就有多少结点,每个结点有2个数据域,一个存放系数,一个存放指数。
如有以下多项式P8(x)=3+8x+9x5+6x8,用上述两种方法表示的示意图分别如下:
方法1示意图
方法2示意图
[算法分析]
算法非常简单,遍历两个单链表,根据指数和系数进行相应的加减,生成一个新链表。
系数为0的结点删除掉(或不生成这种结点),输出该链表。
3.魔术师与扑克问题
13张黑桃扑克(A2345678910JQK),预先排好,正面朝下拿在魔术师的手里,从最上面开始,第一次数一张牌翻过来放在桌面上,正好是“A”;
第二次数两张牌,数1的那张放在手中扑克的最下面,数2的那张翻过来放在桌面上正好是“2”;
……,如此下去,放在桌面上的牌最后正好是“A2345678910JQK”的顺序(从下向上)。
[任务]编程,找出魔术师手中扑克原来的排列顺序(从下向上)。
4.“法雷序列”问题
对任意给定的一个自然数n(n<
=100),将分母小于等于n的不可约的真分数按上升的次序排列,并且在第一个分数前加上0/1,在最后一个分数后加上1/1,这个序列称为n级法雷序列,以Fn表示,例如:
F8=0/1,1/8,1/7,1/6,1/5,1/4,2/7,1/3,3/8,2/5,3/7,1/2,4/7,3/5,5/8,2/3,5/7,3/4,4/5,5/6,6/7,7/8,1/1。
[任务]编程,求出n级法雷序列,每行输出10个分数。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 链表