数据结构实验二 线性表及其应用.docx

上传人:b****6 文档编号:14257148 上传时间:2023-06-21 格式:DOCX 页数:11 大小:21.71KB
下载 相关 举报
数据结构实验二 线性表及其应用.docx_第1页
第1页 / 共11页
数据结构实验二 线性表及其应用.docx_第2页
第2页 / 共11页
数据结构实验二 线性表及其应用.docx_第3页
第3页 / 共11页
数据结构实验二 线性表及其应用.docx_第4页
第4页 / 共11页
数据结构实验二 线性表及其应用.docx_第5页
第5页 / 共11页
数据结构实验二 线性表及其应用.docx_第6页
第6页 / 共11页
数据结构实验二 线性表及其应用.docx_第7页
第7页 / 共11页
数据结构实验二 线性表及其应用.docx_第8页
第8页 / 共11页
数据结构实验二 线性表及其应用.docx_第9页
第9页 / 共11页
数据结构实验二 线性表及其应用.docx_第10页
第10页 / 共11页
数据结构实验二 线性表及其应用.docx_第11页
第11页 / 共11页
亲,该文档总共11页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

数据结构实验二 线性表及其应用.docx

《数据结构实验二 线性表及其应用.docx》由会员分享,可在线阅读,更多相关《数据结构实验二 线性表及其应用.docx(11页珍藏版)》请在冰点文库上搜索。

数据结构实验二 线性表及其应用.docx

数据结构实验二线性表及其应用

第二章 线性表及其应用

【实验目的】

1.熟练掌握线性表的基本操作在顺序存储和链式存储上的实现;

2.以线性表的各种操作(建立、插入、删除、遍历等)的实现为重点;

3.掌握线性表的动态分配顺序存储结构的定义和基本操作的实现;

4.通过本章实验帮助学生加深对C语言的使用(特别是函数的参数调用、指针类型的应用和链表的建立等各种基本操作)。

第一节 知识准备

一、线性表的逻辑结构

线性表是由一组具有相同特性的数据元素组成的有限序列。

至于每个数据元素,它可以是一个数,一个符号,也可以是一页书,甚至更复杂的信息。

     例如:

26个英文字母构成一个线性表 (A,B,C,…,Y,Z)

           一串数字构成另一个线性表    (45,45,32,65,123)

每个数据元素可以由若干数据项组成,常把此数据元素称为记录。

能唯一标识一个记录的数据项的值称为关键字。

如:

一个学校的学生情况表如表2-1所示,表中每个学生的情况为一个记录,它由学号、姓名、性别、年龄、年级等五个数据项组成。

学号姓名性别年龄年级

96001张平女21大二

96002王极男20大一

96003膨磊男23大三

96004严正英女19大一

96005李强男20大二

综上所述,线性表有如下特性:

1.除第一个和最后一个元素以外,每个元素有且仅有一个直接前趋和一个直接后继;第一个结点只有直接后继,最后一个结点只有直接前趋。

2.线性表中的每个数据元素,其数据类型是一致的。

3.数据元素之间的相对位置是线性的,结构中的数据元素之间存在一个对一个的关系。

二、线性表的顺序表示和实现

计算机的内存是由有限多个存储单元组成的,每个存储单元都有对应的整数地址,各存储单元的地址是连续编号的。

对于一个线性表,如果用一组连续的存储单元依次存放它的各个数据元素,这就是线性表的顺序分配。

也就是说,在线性表的顺序分配结构中,逻辑结构上相邻的数据元素,其物理位置也是相邻的。

若一个数据元素只占用一个存储单元,则这种分配方式如图2-1所示。

从图可知,线性表的第i个数据元素的存储地址 LOC(ai)=LOC(a1)+(i-1)

如果一个数据元素占据k个存储单元,则有   LOC(ai)=LOC(a1)+(i-1)×k

其中,LOC(a1)是线性表的第一个数据元素的存储地址。

三、线性表的链式表示和实现

1.单链表

线性链表即线性表的链式存储结构是用一组任意的存储单元(它们可以是连续的,也可以是不连续的)来存储线性表的各个数据元素。

为了表示每个元素与其直接后继元素之间的逻辑关系,对每个元素来说,除了需要存储元素本身的信息之外,还需要存储一个指示其直接后继的信息(即直接后继的存储位置),这两部分信息组成了一个数据元素的存储结构,称之为一个结点(node),当然每一个结点占用的存储单元应该是连续的。

这样,每个结点包括两个域,存储数据元素本身信息的域称之为数据域(data),存储直接后继结点存储位置的域称之为指针域(next),该域内信息为一指针,它指出线性表某一数据元素逻辑上直接后继元素的存储位置。

由于线性表的最后一个数据元素没有后继,故相应结点的指针域内容为空NULL(也可以用符号∧表示)。

如图2-2所示为一个不带头结点的单链表。

在实际应用中,有时也使用带头结点的单链表,如图2-3所示,虽然浪费了一个结点,但是却换来了其它操作的便利,例如在插入删除操作中,不用判断是否对第一个结点进行。

我们称这个结点为“哨兵”,其作用往往是不用判断出界;在以后的学习中,还会经常遇上“哨兵”。

 

2.循环链表

循环链表是线性表的一种特殊的链式存储结构,它的特点是线性链表的最后一个结点(即表尾结点)的指针域存放链表中第一个结点的地址,则整个链表形成了一个环。

如图2-4所示。

3.双向循环链表

双向循环链表是对循环链表的改进,当我们需要经常查找某一节点的前驱时,可以增加一个指向前驱的指针域,构成双向循环链表。

如图2-5所示。

第二节 狐狸逮兔子实验

【问题描述】

围绕着山顶有10个圆形排列的洞,狐狸要吃兔子,兔子说:

“可以,但必须找到我,我就藏身于这十个洞中,你先到1号洞找,第二次隔1个洞(即3号洞)找,第三次隔2个洞(即6号洞)找,以后如此类推,次数不限。

”但狐狸从早到晚进进出出了1000次,仍没有找到兔子。

问兔子究竟藏在哪个洞里?

这实际上是一个反复查找线性表的过程,用以前学过的程序设计的知识也很容易实现,这里希望读者能体会数据结构的思想。

【数据描述】

定义一个顺序表,用具有10个元素顺序表来表示这10个洞。

每个元素分别表示围着山顶的一个洞,下标为洞的编号。

#define LIST_INIT_SIZE 10 //线性表存储空间的初始分配量

typedef struct {

   ElemType *elem; //存储空间基址

   int  length; //当前长度

   int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)

}SqList;

【算法描述】

status InitList_Sq(SqList &L) {

  //构造一个线性表L

  L.elem=(ElemType )malloc(LIST_INIT_SIZE*sizeof(ElemType));

  If(!

L.elem) return OVERFLOW;//存储分配失败

  L.length=0;                //空表长度为0

L.listsize=LIST_INIT_SIZE; //初始存储容量

  return OK;

} //InitList_Sq

status Rabbit(SqList &L)

  { //构造狐狸逮兔子函数

   int current=0; //定义一个当前洞口号的记数器,初始位置为第一个洞口

   for(i=0;i

     L.elem[i]=1;//给每个洞作标记为1,表示狐狸未进之洞

   L.elem[LIST_INIT_SIZE-1]=L.elem[0]=0;//首先进入第一个洞,标记进过的洞为0。

   for(i=2;i<=1000;i++)

{ current=(current+i)%LIST_INIT_SIZE;//实现顺序表的循环引用

   L.elem[i]=0;// 标记进过的洞为0

}//第二次隔1个洞找,第三次隔2个洞找,以后如此类推,经过一千次

    printf("兔子可能藏在如下的洞中:

")

    for(i=0;i

         if(L.elem[i]==1)

printf(“ 第%d个洞\n ”,i+1);//输出未进过的洞号

return OK;

}//end

【C源程序】

#include 

#include 

#define OK  1

#define OVERFLOW -2

typedef int status;

typedef int ElemType;

#define LIST_INIT_SIZE 10 /*线性表存储空间的初始分配量  */

typedef struct {

   ElemType *elem; /* 存储空间基址 */

   int  length; /* 当前长度  */

   int listsize;  /*当前分配的存储容量(以sizeof(ElemType)为单位)*/

}SqList;

status InitList_Sq(SqList *L){

  /*构造一个线性表L  */

  (*L).elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));

   if(!

((*L).elem))   return OVERFLOW; /* 存储分配失败 */

  (*L).length=0; /*空表长度为0   */

(*L).listsize=LIST_INIT_SIZE; /*初始存储容量  */

  return OK;

} /*InitList_Sq  */

status Rabbit(SqList *L){

  /*构造狐狸逮兔子函数   */

   int i,current=0; /*定义一个当前洞口号的记数器,初始位置为第一个洞口*/

   for(i=0;i

     (*L).elem[i]=1;/*给每个洞作标记为1,表示狐狸未进之洞  */

   (*L).elem[LIST_INIT_SIZE-1]=0;

   (*L).elem[0]=0;  /*第一次进入第一个洞,标记进过的洞为0 */

for(i=2;i<=1000;i++)

{ current=(current+i)%LIST_INIT_SIZE;/*实现顺序表的循环引用  */

   (*L).elem[current]=0;/* 标记进过的洞为0  */

}/*第二次隔1个洞找,第三次隔2个洞找,以后如此类推,经过一千次  */

    printf("\n兔子可能藏在如下的洞中:

") ;

    for(i=0;i

 if((*L).elem[i]==1)

    printf("  \n此洞是第%d号洞 ",i+1);/*输出未进过的洞号  */

return OK;

}

void main()

{

SqList *L;

InitList_Sq(L);

Rabbit(L);

getch();

【测试数据】

最后的输出结果为:

2  4  7  9

【说明】

本算法思路比较简单,采用了顺序表表示围着山顶的10个洞,首先对所有洞设置标志为1,然后通过1000次循环,对每次所进之洞修改标志为0,最后输出标志为1的洞。

【实验题】

1.同上面的狐狸逮兔子问题,如果山上有5个洞或20个洞,狐狸从早到晚进进出出了500次或10000次,仍没有找到兔子。

问兔子究竟可能藏在哪个洞里?

2.同上面的问题,将表示洞的线性表采用单链表实现,并比较其差异。

第三节 约瑟夫问题的实现

【问题描述】

设有n个人围坐在圆桌周围,现从某个位置m(1≤m≤n)上的人开始报数,报数到k的人就站出来。

下一个人,即原来的第k+1个位置上的人,又从1开始报数,再报数到k的人站出来。

依此重复下去,直到全部的人都站出来为止。

试设计一个程序求出出列序列。

    这是一个使用循环链表的经典问题。

因为要不断地出列,采用链表的存储形式能更好地模拟出列的情况。

【数据描述】

我们可以建立一个不带头结点的循环链表,其中的n个人用n个结点来表示。

Typedef int Elemtype;

Typedef struct Cnode

  {  Elemtype data;

     struct Cnode *next;

   }CNode;

【算法描述】见图2.5的流程图。

 

Status Create_clist(Clist &clist,int n)

{ clist=null;

  for(i=n;i>=1;i--)

     { if(!

(p=(CNode *)malloc(sizeof(CNode))))

               return overflow; //存储分配失败

       p->data=i;

       p->next=clist;

       clist=p;

       if(i==n) 

 q=p;//用q指向链表的最后一个结点

}

q->next=clist;//把链表的最后一个结点的链域指向链表的第一个结点,构成循环链表

ok;

}//end

status Joseph(int m,int n,int k)

{  if(m>n) return ERROR;//起始位置错

   if(!

Create_clist(clist,n))

     return ERROR;//循环链表创建失败

   p=clist;

   for(i=1;i

      p=p->next;//p指向m位置的结点

   while(p)

      { for(i=1;i

           p=p->next;//找出第k个结点

       q=p->next;

       printf(“%d”,q->data);//输出应出列的结点

       if(p->next==p)  

          p=null;//删除最后一个结点

         else { p->next=q->next;//删除第K个结点

                p=p->next;//使P指向第k+1个元素位置

                free(q); }

       }  //while

      clist=null;

 } //end    

【C源程序】

#include 

#include 

#define NULL 0

#define OK 1

#define ERROR 0

#define OVERFLOW -2

typedef int Status;

typedef int Elemtype;/*定义数据元素类型  */

typedef struct Cnode

  {  Elemtype data;

     struct Cnode *next;

   }CNode;

CNode *joseph;/*定义一个全局变量  */

Status Create_clist(CNode *clist,int n)

{  CNode *p,*q;

int i;

clist=NULL;

   for(i=n;i>=1;i--)

     { p=(CNode *)malloc(sizeof(CNode));

       if(p==NULL)

               return OVERFLOW; /*存储分配失败  */

       p->data=i;

       p->next=clist;

       clist=p;

       if(i==n)

 q=p;/*用q指向链表的最后一个结点  */

}

q->next=clist; /*把链表的最后一个结点的链域指向链表的第一个结点,构成循环链表  */

joseph=clist;  /*把创建好的循环链表头指针赋给全局变量  */

return OK;

}           /*end  */

Status Joseph(CNode *clist,int m,int n,int k)

{  int i;

CNode *p,*q;

if(m>n) return ERROR;/*起始位置错  */

     if(!

Create_clist(clist,n))

     return ERROR;/*循环链表创建失败  */

   p=joseph;/*p指向创建好的循环链表  */

   for(i=1;i

      p=p->next;/*p指向m位置的结点  */

   while(p)

      { for(i=1;i

           p=p->next;/* 找出第k个结点  */

       q=p->next;

       printf("%d ",q->data);/*输出应出列的结点  */

       if(p->next==p)

  p=NULL;/*删除最后一个结点  */

         else { p->next=q->next;

                p=p->next;

free(q); }

       }  /*while  */

      clist=NULL;

 } /* end */

void main( )

{ int m,n,k,i;

  CNode *clist;

  clist=NULL;/*初始化clist  */

printf("\n请输入围坐在圆桌周围的人数n:

");

scanf("%d",&n);

printf("\n请输入第一次开始报数人的位置m:

");

scanf("%d",&m);

printf("\n你希望报数到第几个数的人出列?

");

scanf("%d",&k);

Create_clist(clist,n);/*创建一个有n个结点的循环链表clist  */

printf("\n出列的顺序如下:

\n");

Joseph(clist,m,n,k);

getch();

}/*main  */

【测试数据】

1、请输入围坐在圆桌周围的人数n:

7

   请输入第一次开始报数人的位置m:

3

   你希望报数到第几个数的人出列?

 2

   出列的顺序如下:

4 6 1 3 7 5 2

2、请输入围坐在圆桌周围的人数n:

13

   请输入第一次开始报数人的位置m:

5

   你希望报数到第几个数的人出列?

 6

   出列的顺序如下:

10 3 9 4 12 7 5 2 6 11 8 1 13

3、请输入围坐在圆桌周围的人数n:

21

   请输入第一次开始报数人的位置m:

3

   你希望报数到第几个数的人出列?

 9

   出列的顺序如下:

11 20 8 18 7 19 10 2 15 9 4 1 21 3 6 14 12 13 5 16 17

【说明】

本算法采用一个不带表头的循环链表来处理约瑟夫问题,在此算法中,每次找出需出列结点,要经过k次循环移动定位指针,全部结点出列,需经过n个k次循环,因此,本算法的时间复杂度为O(k*n)。

实际问题的处理中,有许多与约瑟夫问题类似,都可以采用此方法完成。

【实验题】

1.处理约瑟夫问题也可用数组完成,请读者自己编写使用数组实现约瑟夫问题的算法和程序。

2.猴王问题。

某森林中有n只猴子在商量猴王选举问题,所有的猴子都想当猴王,因此大家商量了一个选举办法如下:

所有的猴子围成一圈,先从第一个猴子开始报数,报数到13的猴子就出列。

紧接着的下一个猴子,又从1开始进行新的一轮报数,报数到12的猴子再出列;依此重复下去,每一轮报数都比上一轮的报数少1,直到报数减为1之后,又从13开始报数。

直到原列中只剩下一个猴子为止,这个猴子就是猴王。

试设计一个程序求出猴王。

第四节 思考题

1.假设有两个按元素值递增有序排列的线性表A和B,均以单链表作存储结构,请编写算法将表A和表B归并成一个按元素非递减有序(允许值相同)排列的线性表C,并要求利用原表(即表A和表B)的结点空间存放表C。

               (上海交通大学一九九九年硕士生入学考试试题)

【简要分析】除了指向线性表C头结点的指针外,还需设置三个指针Pa,Pb,Pc;首先Pa,Pb分别指向线性表A和B的表头,Pc指向A和B的表头值较小的结点,线性表C头节点的指针等于Pc;然后,比较Pa与Pb的值的大小,让Pc的后继指向较小值的指针,接着Pc向后移动,较小值的指针也向后移动,以此类推,直到Pa,Pb中某一个为空,这时,让Pc的后继指向Pa,Pb中非空的指针就完成了C表的建立。

2.给定一个整数数组b[0..N-1], b中连续相等元素构成的子序列称为平台.试设计算法,求出b中最长平台的长度.

(中科院计算机技术研究所1999年硕士入学考试数据结构与程序设计试题)

【简要分析】设置一个平台长度变量Length和一个计数器Sum。

初始化Length为1,Sum为1,再设置两下标指针i、j,首先,i指向第一个数组元素,j指向其次的第二个元素,比较i、j指向元素值的大小,若相等,则Sum++,i++,j++,再次比较i、j指向元素值的大小;若不相等,则比较Length与Sum的大小,如果Sum值大于Length,则把Sum的值赋给Length,Sum的值重置为1,同时i,j也向前各移动一位;重复上面的过程,直到i指向最后一个元素为止,此时的Length就是最长平台的长度。

3.参加知识竞赛的n个学校(编号为1…n),每个学校派至多m名学生参赛,每个学生的编号有二位学校代码和五位座位编号构成。

统计每个学校的参赛学生的平均分,并依次确定学校的名次;查找竞赛的最高分和最低分,并计算它们的方差;给出前三名学生的具体信息。

【简要分析】本题解决办法较多。

我们可以采用单链表来对所有学生的信息进行存储,至多需要n*m个结点,每个结点至少包含如下几个域:

2位学校代码、5位座位编号、学生姓名、竞赛成绩等。

也可以采用顺序表来对所有学生的信息进行存储,构造一个结构体数组,至多需要n*m个数组元素,每个数组元素的数据项值与单链表中的结点域值类似。

然后再另外构造一个存储学校信息的顺序表或单链表,每个结点至少包含如下几个域:

二位学校代码、学校名称、学校取得的平均分、学校名次等。

在构造好所有的存储结构之后,就可以编制相应的计算平均分、排序、查找、输出等算法了。

Chapter Two     Linear_List and its applications

Objectives

1.To understand basic operations of Linear_List in implementation of Sequence_List and Link_List.

2.To focus on basic operations of Linear_List, such as, creation, insertion, deletion and traversal.

3.To understand definition and basic operation of dynamic allocation list.

4.To help students better understand applications of C program language through experiments. Especially, focus on function call, application of pointer type and creation of Link_List, etc.   

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

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2