信息学奥赛数据结构教程PASCAL版Word文件下载.docx

上传人:b****3 文档编号:17829239 上传时间:2022-12-11 格式:DOCX 页数:11 大小:61.45KB
下载 相关 举报
信息学奥赛数据结构教程PASCAL版Word文件下载.docx_第1页
第1页 / 共11页
信息学奥赛数据结构教程PASCAL版Word文件下载.docx_第2页
第2页 / 共11页
信息学奥赛数据结构教程PASCAL版Word文件下载.docx_第3页
第3页 / 共11页
信息学奥赛数据结构教程PASCAL版Word文件下载.docx_第4页
第4页 / 共11页
信息学奥赛数据结构教程PASCAL版Word文件下载.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

信息学奥赛数据结构教程PASCAL版Word文件下载.docx

《信息学奥赛数据结构教程PASCAL版Word文件下载.docx》由会员分享,可在线阅读,更多相关《信息学奥赛数据结构教程PASCAL版Word文件下载.docx(11页珍藏版)》请在冰豆网上搜索。

信息学奥赛数据结构教程PASCAL版Word文件下载.docx

 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;

   data:

integer;

   next:

var

 head,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的直接前趋}

  r:

{尾指针后移一个}

  read(x);

 end;

 r^.next:

{最后一个结点的指针域赋空}

 readln;

output:

'

{输出}

 p:

=head^.next;

{头指针没有数据,只要从第一个结点开始就可以了}

 whilep^.next<

nildo

  write(p^.data:

4);

  p:

=p^.next;

 write(p^.data:

{最后一个结点的数据单独输出,也可以改用REPEAT循环}

end.{请大家改写这个程序,把链表的实际结点个数存入到头结点中,并输出}

(三)单链表的操作

1.查找“数据域满足一定条件的结点”

=head^next;

  while(p^.data<

x)and(p^.next<

nil)dop:

{找到第一个就结束}

  ifp^.data=xthen找到了处理else输出不存在;

 如果想找到所有满足条件的结点,则修改如下:

  whilep^.next<

nildo{一个一个判断}

  begin

   ifp^.data=xthen找到一个处理一个;

   p:

2.取出单链表的第i个结点的数据域

functionget(head:

i:

integer):

j:

 j:

=1;

 while(p<

nil)and(j<

i)do

  j:

=j+1;

 if(p<

nil)and(j=i)thenwriteln(p^.data)

 elsewriteln(‘inotexsit!

’);

end;

3.插入一个结点在单链表中去

procedureinsert(head:

x:

integer);

{插入X到第i个元素之前}

 p,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):

 n:

 whilep<

nildo

  n:

=n+1;

 len:

=n;

(四)双向链表

  每个结点有两个指针域和若干数据域,其中一个指针域指向它的前趋结点,一个指向它的后继结点。

它的优点是访问、插入、删除更方便,速度也快了。

但“是以空间换时间”。

  数据结构的定义:

   typepointer=^nodetype;

     nodetype=record

       data:

       pre,next:

{pre指向前趋,next指向后继}

     end;

   varhead,p,q,r:

  下面给出双向链表的插入和删除过程。

Procedureinsert(head:

i,x:

{在双向链表的第i个结点之前插入X}

Var

 s,p:

Begin

 New(s);

 S^.data:

 P:

{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个结点}

 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:

 head,p,q:

 n,m:

 procedurecreat(varhead:

n:

{建立一个单向循环链表}

 var

  p,q:

  i:

{建立头结点}

  head:

  p^.num:

  q:

{q指向链表的尾结点}

  fori:

=2tondo{建立链表}

   new(p);

   p^.num:

=i;

   q^.next:

{把P结点连接到q的后面}

   q:

  q^.next:

{建立循环链表}

 procedureselectking(varhead:

varm:

  i,count:

  count:

{指向第一个结点,洋计数1}

{q为p的前趋}

  repeat

=q^.next;

   count:

=count+1;

   ifcountmodm=0thenbegin{该猴子出圈,即删除结点}

    q^.next:

    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

end.

[运行测试]

输入:

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}

 p1,p2,p3:

{临时用工作指针,一般不能破坏头指针}

 p1:

=h1^.next;

 p2:

=h2^.next;

 h3:

=h1;

{新链表共用第一个链表,简化,也可以另外开辟一个头结点}

 p3:

=h3;

 while(p1<

nil)and(p2<

nil)do{归并}

  ifp1^.data<

=p2^.datathen

  begin{将p1结点链接到p3中去}

   p3^.next:

=p1;

{指向}

   p3:

{p3后移}

   p1:

=p1^.next{p1后移}

  end

  elsebegin{将p2结点链接到p3中去}

   p2:

=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个分数。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1