数据结构实验报告顺序表与链表.docx
《数据结构实验报告顺序表与链表.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告顺序表与链表.docx(28页珍藏版)》请在冰豆网上搜索。
数据结构实验报告顺序表与链表
实验二顺序表与链表
【实验目的】
1、掌握线性表中元素的前驱、后续的概念。
2、掌握顺序表与链表的建立、插入元素、删除表中某元素的算法。
3、对线性表相应算法的时间复杂度进行分析。
4、理解顺序表、链表数据结构的特点(优缺点)。
【实验学时】
4学时
【实验预习】
回答以下问题:
1、顺序表的存储表示
假设线性表中每一个数据元素的存储空间大小为1个字节,并且以其所占存储空间的第一个字节的地址作为该元素的存储位置,则线性表中任一个数据元素的存储位置为:
LOC(Ai)=LOC(A1)+(i-1)*1
其中,LOC(A1)为线性表中第一个数据元素a1的存储位置,也称为线性表的起始位置(首地址)。
typedefstructSqlist
{
ElemType*slist;//存储空间的基地址
intlength;//表长度
intlistsize;//当前分配的存储空间容量
}Sqlist;
2、单链表的存储表示
线性链表也称单链表,在每一个结点中只包含一个指针,用于指示该结点的直接后继结点,整个链表通过指针相连,最后一个结点因为没有后继结点,其指针置为空(NULL)。
这样,链表中所有数据元素(结点)构成一对一的逻辑关系,实现线性表的链式存储。
【实验内容和要求】
1、按照要求完成程序exp2_1.c,实现顺序表的相关操作。
以下函数均具有返回值,若操作完成,返回OK,操作失败返回ERROR。
函数需返回的其他数据,使用函数参数返回。
exp2_1.c部分代码如下:
#include
#include
#defineERROR0
#defineOK1
#defineINIT_SIZE100
#defineINCREM10
typedefintElemType;/*定义表元素的类型*/
/*
(1)---补充顺序表的存储分配表示,采用定长和可变长度存储均可*/
typedefstructSqlist
{
ElemType*slist;//基地址
intlength;//表长度
intlistsize;//分配的空间
}Sqlist;
/*函数声明*/
intInitList_sq(Sqlist*L);
intCreateList_sq(Sqlist*L,intn);
intListInsert_sq(Sqlist*L,inti,ElemTypee);
intPrintList_sq(Sqlist*L);
intListDelete_sq(Sqlist*L,inti,ElemType*e);
intListLocate(Sqlist*L,ElemTypee,int*pos);
intmenu_select();
/*
(2)---顺序表的初始化*/
intInitList_sq(Sqlist*L)
{
L->slist=(ElemType*)malloc(INIT_SIZE*sizeof(ElemType));
if(!
L->slist)
{
returnERROR;
}
L->length=0;
L->listsize=INIT_SIZE;//初始空间容量
returnOK;
}/*InitList*/
/*(3)---创建具有n个元素的顺序表*/
intCreateList_sq(Sqlist*L,intn)
{
ElemTypee;
inti;
for(i=0;i{
printf("inputdata%d:
",i+1);
scanf("%d",&e);
if(!
ListInsert_sq(L,i+1,e))
{
returnERROR;
}
}
returnOK;
}/*CreateList*/
/*(4)---输出顺序表中的元素*/
intPrintList_sq(Sqlist*L)
{
inti;
for(i=1;i<=L->length;i++)
{
printf("%5d",L->slist[i-1]);
}
returnOK;
}/*PrintList*/
/*(5)---在顺序表的第i个位置之前插入新元素e*/
intListInsert_sq(Sqlist*L,inti,ElemTypee)
{
intk;
if(i<1||i>L->length+1)
{
returnERROR;
}
if(L->length>=L->listsize)//当前空间已满,申请新的空间
{
L->slist=(ElemType*)realloc(L->slist,(L->listsize+INCREM)*sizeof(ElemType));
if(!
L->slist)
{
returnERROR;
}
L->listsize+=INCREM;
}
for(k=L->length-1;k>=i-1;k--)
{
L->slist[k+1]=L->slist[k];
}
L->slist[i-1]=e;
L->length++;
returnOK;
}/*ListInsert*/
/*(6)---在顺序表中删除第i个元素,e返回删除的元素*/
intListDelete_sq(Sqlist*L,inti,ElemType*e)
{
intj;
if(i<1||i>L->length)
{
returnERROR;
}
*e=L->slist[i-1];
for(j=i;ilength;j++)
{
L->slist[j-1]=L->slist[j];
}
L->length--;
returnOK;
}/*ListDelete_sq*/
/*(7)---在顺序表中查找指定值元素,pos为返回其位置序号*/
intListLocate(Sqlist*L,ElemTypee,int*pos)
{
ElemType*end=L->slist+L->length;
ElemType*p=L->slist;
inti;
for(i=1;p{
if(*p==e)
{
*pos=i;
break;
}
i++;
}
if(p>=end)
{
returnERROR;
}
else
{
returnOK;
}
}/*ListLocate*/
/*定义菜单字符串数组*/
intmenu_select()
{
char*menu[]={"\n***************MENU******************\n",
"1.CreateList\n",/*创建顺序表*/
"2.GetElement\n",/*查找顺序表中的元素*/
"3.Insertdata\n",/*插入数据*/
"4.Deletedata\n",/*删除数据*/
"0.Quit\n",/*退出*/
"\n***************MENU******************\n"
};
chars[3];/*以字符形式保存选择号*/
intc,i;/*定义整形变量*/
for(i=0;i<7;i++)/*输出主菜单数组*/
printf("%s",menu[i]);
do
{
printf("\nEnteryouchoice(0~4):
");/*在菜单窗口外显示提示信息*/
scanf("%s",s);/*输入选择项*/
c=atoi(s);/*将输入的字符串转化为整形数*/
}
while(c<0||c>4);/*选择项不在0~4之间重输*/
returnc;/*返回选择项,主程序根据该数调用相应的函数*/
}
/*主函数*/
intmain()
{
Sqlistsl;
InitList_sq(&sl);
intn;
intm,k;
printf("pleaseinputn:
");/*输入顺序表的元素个数*/
scanf("%d",&n);
if(n==0)printf("ERROR");
for(;;)/*无限循环*/
{
switch(menu_select())/*调用主菜单函数,返回值整数作开关语句的条件*/
{
case1:
printf("\n1-CreateSqlist:
\n");
CreateList_sq(&sl,n);
printf("\nPrintSqlist:
\n");
PrintList_sq(&sl);
break;
case2:
printf("\n3-GetElemfromSqlist:
\n");
printf("pleaseinputsearchdata:
");
scanf("%d",&k);
intpos;
if(!
ListLocate(&sl,k,&pos))
printf("Notfound");
else
{
printf("foundtheelement,positionis%d\n",pos);
printf("\nPrintSqlist:
\n");
PrintList_sq(&sl);
}
break;
case3:
printf("\n4-InsertfromSqlist:
\n");
printf("\ninputinsertlocationanddata:
(location,data)\n");
scanf("%d,%d",&m,&k);
if(ListInsert_sq(&sl,m,k))
{
printf("\nOK\n");
printf("\nPrintSqlist:
\n");
PrintList_sq(&sl);
}
else
printf("\nERROR!
");
break;
case4:
printf("\n5-DeletefromSqlist:
\n");
printf("\npleaseinputdeletelocation\n");
scanf("%d",&k);
intdeldata;
if(ListDelete_sq(&sl,k,&deldata))
{
printf("\nOK\n");
printf("\nDeletedatais%d\n",deldata);
printf("\nPrintSqlist:
\n");
PrintList_sq(&sl);
}
else
printf("\nERROR!
");
break;
case0:
exit(0);/*如菜单返回值为0程序结束*/
}
}
return0;
}
2、按照要求完成程序exp2_2.c,实现单链表的相关操作。
exp2_2.c部分代码如下:
#include
#include
#defineERROR0
#defineOK1
typedefintElemType;/*定义表元素的类型*/
/*
(1)---线性表的单链表存储表示*/
typedefstructLNode
{
ElemTypedata;
structLNode*next;
}LNode,*LinkList;
LNode*InitList(LinkListL);/*带头结点单链表初始化*/
voidPrintList(LinkListL);/*输出带头结点单链表的所有元素*/
intGetElem(LinkListL,inti,ElemType*e);/*查找第i位置的元素,并由e返回其值*/
intInsertElem(LinkListL,inti,ElemTypee);/*在第i个位置插入元素e*/
intDeleteElem(LinkListL,inti,ElemType*e);/*删除第i位置的元素,并由e返回其值*/
voidDestroyLinkList(LinkListL);/*释放链表及其空间*/
LinkListCreateList(intn);/*创建n个结点的单链表*/
intmenu_select();/*菜单函数*/
/*带头结点单链表初始化*/
LNode*InitList(LinkListL)
{
L=(LNode*)malloc(sizeof(LNode));/*申请一个头结点*/
if(!
L)returnERROR;/*申请失败*/
L->next=NULL;/*头结点的指针域置空*/
returnL;
}
/*
(1)---输出带头结点单链表的所有元素*/
voidPrintList(LinkListL)
{
LNode*p;
p=L->next;
while(p!
=NULL)
{
printf("%5d",p->data);
p=p->next;
}
}/*PrintList*/
/*
(2)---在单链表的第i个位置插入元素e,若插入成功返回OK,插入失败返回ERROR*/
intInsertElem(LinkListL,inti,ElemTypee)
{
LNode*p=L,*s;
intj=0;
while(p&&j{
p=p->next;
j++;
}
if(!
p||j>i-1)
{
returnERROR;
}
s=(LNode*)malloc(sizeof(LNode));
if(!
s)
{
returnERROR;
}
s->data=e;
s->next=p->next;
p->next=s;
returnOK;
}/*InsertElem*/
/*(3)---查找第i位置的元素,若存在返回OK并由e返回其值,若不存在返回ERROR*/
intGetElem(LinkListL,inti,ElemType*e)
{
LNode*p;
intj=1;
while(p&&j
{
p=p->next;
j++;
}
if(!
p||j>i)
{
returnERROR;
}
*e=p->data;
returnOK;
}/*GetElem*/
/*(4)---删除第i位置的元素,成功返回OK,并由e返回其值,若不成功返回ERROR,注意删除的结点必须释放其所占空间*/
intDeleteElem(LinkListL,inti,ElemType*e)
{
LNode*p=L,*s;
intj=0;
while(p&&j{
p=p->next;
j++;
}
if(!
p||j>i-1)
{
returnERROR;
}
s=p->next;
p->next=s->next;
*e=s->data;
free(s);
returnOK;
}/*DeleteElem*/
/*(5)---创建具有n个结点的单链表,创建成功返回其头指针*/
LinkListCreateList(intn)
{
LNode*p,*q,*head;
inti;
head=(LinkList)malloc(sizeof(LNode));
head->next=NULL;
p=head;
for(i=0;i{
q=(LinkList)malloc(sizeof(LNode));
printf("inputdata%d",i+1);
scanf("%d",&q->data);
q->next=NULL;//节点指针域置空
p->next=q;//新节点连接在表末尾
p=q;
}
returnhead;
}/*CreateList*/
/*释放链表及其空间*/
voidDestroyLinkList(LinkListL)
{
LNode*p=L,*q;
while(p)
{
q=p->next;
free(p);
p=q;
}
}/*DestroyLinkList*/
intmenu_select()
{
char*menu[]={"\n***************MENU******************\n",
"1.InitLinkList\n",/*初始化链表*/
"2.GetElement\n",/*查找元素*/
"3.Insertdata\n",/*插入元素*/
"4.Deletedata\n",/*删除元素*/
"5.CreateLinkList\n",/*创建具有n个元素的链表*/
"0.DestroyLinkList&&Quit\n",/*释放链表所占空间&退出*/
"\n***************MENU******************\n"
};
chars[3];/*以字符形式保存选择号*/
intc,i;/*定义整形变量*/
for(i=0;i<8;i++)/*输出主菜单数组*/
{
printf("%s",menu[i]);
}
do
{
printf("\nEnteryouchoice(0~5):
");/*在菜单窗口外显示提示信息*/
scanf("%s",s);/*输入选择项*/
c=atoi(s);/*将输入的字符串转化为整形数*/
}
while(c<0||c>5);/*选择项不在0~5之间重输*/
returnc;/*返回选择项,主程序根据该数调用相应的函数*/
}
intmain()
{
inti,n;
ElemTypee;
LinkListL=NULL;/*定义指向单链表的指针*/
for(;;)/*无限循环*/
{
switch(menu_select())/*调用主菜单函数,返回值整数作开关语句的条件*/
{
/*值不同,执行的函数不同,break不能省略*/
case1:
printf("\n1-InitLinkList:
\n");
L=InitList(L);
if(L!
=NULL)
printf("\nInitLinkListOK!
\n");
else
printf("\nInitLinkListError!
\n");
break;
case2:
printf("\n2-GetElemfromLinkList:
\n");
printf("inputpos=");
scanf("%d",&i);
if(L!
=NULL&&GetElem(L,i,&e))
{
printf("No%iis%d",i,e);
printf("\nPrintfList:
\n");
PrintList(L);
}
else
printf("Error&Notexists!
");
break;
case3:
printf("\n3-InserteintoLinkList:
\n");
printf("inputpos=");
scanf("%d",&i);
printf("inpute=");
scanf("%d",&e);
if(L!
=NULL&&InsertElem(L,i,e))
{
printf("\nInsertOK!
\n");
printf("\nPrintfList:
\n");
PrintList(L);
}
else
printf("\nInsertError!
\n");
break;
case4:
printf("\n4-DeletefromLinkList:
\n");
printf("inputpos=");
scanf("%d",&i);
if(L!
=NULL&&DeleteElem(L,i,&e))
{
printf("\nOK\n");
printf("\nDeletedatais%d\n",e);
printf("\nPrintfList:
\n");
PrintList(L);
}
else
printf("\nDeleteError!
\n");
break;
case5:
printf("pleaseinputn:
");/*输入单链表的元素个数*/
scanf("%d",&n);
if(n<0)
{
printf("ERROR");
break;
}
printf("\nCreateLinkList......\n");
L=CreateList(n);
if(L==NULL)
{
printf("Error!
\n");
break;
}
printf("\nPrintfList:
\n");
PrintList(L);
break;
case0:
printf("\nDestroylinklistandfreememory......\n");
if(L!
=NULL)
{
DestroyLinkList(L);
L=NULL;
}
exit(0);/*如菜单返回值为0程序结束*/
}
}
return0;
}
3、循环链表的应用(约瑟夫回环问题)
用整数序列1,2,3,…,n表示顺序坐在圆桌周围的人,并采用循环链表作为存储结构。
任意位置k开始计数,计到m让此位置的人出局,重复上述过程,直至只剩下最后一个人。
依次输出每个出局的人的序号。
提示:
用一个无头结点的循环单链表来实现n个元素的存储。
exp2_3.c部分代码如下:
#include
#include
#defineERROR0
#defineOK1
typedefintElemType;/*定义表元素的类型*/
typedefstructLNode/*线性表的单链表存储*/
{
ElemTypedata;
structLNode*next;
}LNode,*