线性表的操作与应用算法与数据结构课程设计.docx
《线性表的操作与应用算法与数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《线性表的操作与应用算法与数据结构课程设计.docx(16页珍藏版)》请在冰豆网上搜索。
![线性表的操作与应用算法与数据结构课程设计.docx](https://file1.bdocx.com/fileroot1/2023-5/27/db467431-26ff-4c60-9b2d-eb1fa7e27d67/db467431-26ff-4c60-9b2d-eb1fa7e27d671.gif)
线性表的操作与应用算法与数据结构课程设计
线性表的操作与应用
一、问题描述
线性表是一种常见的数据结构,它在实际中有着广泛的应用。
本文要求实现线性表的就地逆置操作,并选择合适的存储结构,以同学录为例完成线性表的建立、查找、插入、删除、修改等操作来实现有关线的操作与应用。
二、基本要求
1、采用顺序和链式存储结构,分别实现线性表的就地逆置操作;
2、采用双向链表,实现报数游戏:
即n个人报数,先向n端报数,报到m出列。
当报数到达表尾时,再向表尾向1端报数。
如此反复,求出列顺序。
3、选择合适的存储结构,以同学录为例完成线性表的建立、查找、插入、删除、修改等操作。
三、测试数据
1、就地逆置的数据为:
13579
2、报数游戏的数据为:
10个人1到3报数
3、同学录得数据为:
1)建立的数据:
学号姓名性别
101liningnan
228zhougaonan
335fangqiannv
2)查找的数据:
学号:
228
3)插入的数据:
434meixunan
4)删除的数据:
学号:
228
5)修改的数据:
335fangqiannan
四、算法思想
1、就地逆置的算法思想:
1)链式结构:
从头到尾扫描单链表L,将头节点的next域置为NULL,将原链表的每个元素节点依次插入头节点。
2)顺序结构:
利用原有的存储空间,设置一个变量t,再利用循环表的两个方向向表中间进行表头表尾的交换。
2、报数游戏的算法思想:
在实现双向链表的基本操作:
建立,插入,删除后,用for循环从1到m报数,在循环中:
1)用标志ch判断是向前或向后报数。
2)当到达表头或表尾时,改变指针方向和报数方向。
3)每当报数到3或只剩两个结点时,删除所报数在的结点,并将m置为-1。
3、同学录的算法思想:
选择链式结构作为个人信息的存储结构,用链表的基本操作:
建立、插入、删除等算法,完成同学录的建立、查询、显示信息等功能,再用switch语句来判断想要实现的功能。
五、模块划分
1、就地逆置
链式结构:
1)voidInitList(LinkList*L),初始化链表。
2)voidDestroyList(LinkList*L),销毁链表。
3)voidClearList(LinkList*L),清空链表。
4)intListEmpty(LinkListL),判断链表是否为空。
若为空,则返回1;反之,则返回0。
5)voidListTraverse(LinkListL),遍历链表并输出。
6)voidCreateList(LinkList*L,ElemTypea[],intn),后接法建立顺序链表。
7)voidreverse(SqList*L,ElemTypea[],intn),逆置顺序表。
8)main(),主函数。
顺序结构:
1)voidInitList(SqList*L),初始化链表。
2)voidDestroyList(SqList*L),销毁链表。
3)voidClearList(SqList*L),清空链表。
4)intListLength(SqListL),求链表的长度。
5)voidListTraverse(SqListL),遍历链表并输出。
6)voidInputElem(SqList*L,ElemTypea[],intn),由预置数组输入顺序表元素。
7)voidreverse(SqList*L,ElemTypea[],intn),逆置顺序表。
8)main(),主函数。
2、报数游戏:
1)voidInitList(LinkList*L),初始化链表。
2)voidListTraverse(LinkListL),遍历链表。
3)voidCreateList(LinkList*L,ElemTypea[],intn),建立双向链表4)4)voidysf(LinkList*L,intm),约瑟夫函数。
5)voidmain()主函数:
用以个while循环和switch选择结构进行进行循环交互性操作。
3、同学录:
1)voidadd(Stud*head)来实现同学录的建立。
2)voidsearch(Stud*head,intid)查询学生信息。
3)voiddel(Stud*head,intid)删除学号为id的学生的信息。
4)voidrewrite(Stud*head,intid)修改学号为id的学生的信息。
5)voidprint(Stud*head)显示建立好的同学录。
6)voidmain()主函数:
用以个while循环和switch选择结构进行进行循环交互性操作。
六、数据结构//(ADT)
1、链表的存储结构:
typedefstructLNode{
ElemTypedata;
structLNode*next;}LNode,*LinkList;
2、顺序表的存储结构*/
typedefstruct{
ElemType*elem;
intlength;}SqList;
3、学生信息:
typedefstructStudent{
intid;
charname[20];
charsex[20];
structStudent*next;
}Stud;
七、源程序
#include"malloc.h"
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"stdio.h"
#include"stdlib.h"
TypedefintElemType;
程序1:
链式存储结构,实现线性表的就地逆置
typedefstructLNode{
ElemTypedata;
structLNode*next;}LNode,*LinkList;
voidInitList(LinkList*L)
{*L=(LinkList)malloc(sizeof(LNode));
(*L)->next=NULL;}
voidDestroyList(LinkList*L)
{LinkListp;
while(*L!
=NULL)
{p=*L;
*L=(*L)->next;
free(p);}
}
voidClearList(LinkList*L)
{LinkListp;
p=(*L)->next;
while(p!
=NULL)
{(*L)->next=p->next;
free(p);
p=(*L)->next;}
}
intListEmpty(LinkListL)
{if(L->next==NULL)
return1;
else
return0;}
voidListTraverse(LinkListL)
{LinkListp;
printf("\nList:
\t");
p=L->next;
while(p!
=NULL)
{printf("%d\t",p->data);
p=p->next;}
}
voidCreateList(LinkList*L,ElemTypea[],intn)
{LinkListp,new;inti;
p=*L;
for(i=0;i{new=(LinkList)malloc(sizeof(LNode));
new->data=a[i];
p->next=new;p=p->next;}
p->next=NULL;
}
voidreverse(LinkList*L)
{LinkListp,q,r;
p=(*L)->next;q=NULL;
while(p!
=NULL)
{r=p->next;
p->next=q;
q=p;
p=r;
}
(*L)->next=q;
}
main()
{LinkListLa;ElemTypea[]={1,3,5,7,9};
InitList(&La);
CreateList(&La,a,5);
ListTraverse(La);
reverse(&La);
ListTraverse(La);
DestroyList(&La);
}
程序2:
顺序存储结构,实现线性表的就地逆置
typedefstruct{
ElemType*elem;
intlength;}SqList;
voidInitList(SqList*L)
{L->elem=(ElemType*)malloc(N*sizeof(ElemType));
L->length=0;}
voidDestroyList(SqList*L)
{free(L->elem);}
voidClearList(SqList*L)
{L->length=0;}
intListLength(SqListL)
{returnL.length;}
voidListTraverse(SqListL)
{inti;
printf("\nList:
\t");
for(i=0;iprintf("%d\t",L.elem[i]);}
voidInputElem(SqList*L,ElemTypea[],intn)
{inti;
for(i=0;iL->elem[i]=a[i];
L->length=n;}
voidreverse(SqList*L,ElemTypea[],intn)
{inti,t;
for(i=0;iL->elem[i]=a[i];
for(i=0;i<=(n-1)/2;i++)
{t=L->elem[i];
L->elem[i]=L->elem[n-1-i];
L->elem[n-1-i]=t;}
}
main()
{SqListLa;ElemTypea[]={1,3,5,7,9};
InitList(&La);
InputElem(&La,a,5);ListTraverse(La);
reverse(&La,a,5);
ListTraverse(La);
}
程序3:
报数游戏
typedefstructLNode{
ElemTypedata;
structLNode*prior;
structLNode*next;}LNode,*LinkList;
voidInitList(LinkList*L)
{*L=(LinkList)malloc(sizeof(LNode));
(*L)->next=NULL;}
voidListTraverse(LinkListL)
{LinkListp;
printf("\nList:
\t");
p=L->next;
while(p!
=L)
{printf("%3d",p->data);
p=p->next;}
printf("\n");
}
voidCreateList(LinkList*L,ElemTypea[],intn)
{LinkListp,new;inti;
p=*L;
for(i=0;i{new=(LinkList)malloc(sizeof(LNode));
new->data=a[i];new->prior=p;new->next=*L;
p->next=new;(*L)->prior=new;p=p->next;
}
}
voidysf(LinkList*L,intm)
{LinkListp,q;intcount;intch;
printf("输出约瑟夫序列:
");
ch=0;p=(*L);
for(count=0;count{if(!
ch){p=p->next;}
if(ch){p=p->prior;}
if(p==*L)
{if(!
ch){p=p->prior;count--;ch=!
ch;}
elseif(ch){p=p->next;count--;ch=!
ch;}
}
if(count==2||p->next->next==p)
{if(!
ch){q=p->prior;}
if(ch){q=p->next;}
printf("%3d",p->data);
count=-1;
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);p=q;}
if((*L)->prior==*L&&(*L)->next==*L){printf("\n\n");return;}
}
}
main()
{LinkListLa;ElemTypea[]={1,2,3,4,5,6,7,8,9,10};
InitList(&La);
CreateList(&La,a,10);ListTraverse(La);
ysf(&La,3);
}
程序4:
同学录
typedefstructStudent
{charid[20];
charname[20];
charsex[20];
structStudent*next;
}Stud;
voidadd(Stud*head)
{Stud*p=(Stud*)malloc(sizeof(Stud));
printf("请输入学号:
");scanf("%s",&p->id);
printf("请输入姓名:
");scanf("%s",&p->name);
printf("请输入性别:
");scanf("%s",&p->sex);
p->next=head->next;
head->next=p;
}
voidsearch(Stud*head,char*id)
{Stud*p=head->next;
while(p!
=NULL)
{if(strcmp(p->id,id)==0)
{printf("学号:
%s",&p->id);
printf("姓名:
%s",&p->name);
printf("性别:
%s",&p->sex);
break;}
else
{p=p->next;}
}
}
voiddel(Stud*head,char*id)
{Stud*p=head;
while(p->next!
=NULL)
{if(strcmp(p->next->id,id)==0)
{Stud*q=p->next;
p->next=q->next;
free(q);break;}
else
{p=p->next;}
}
}
voidrewrite(Stud*head,char*id)
{Stud*p=head;
while(p->next!
=NULL)
{if(strcmp(p->next->id,id)==0)
{Stud*q=p->next;
p->next=q->next;
free(q);break;}
else
{p=p->next;}
}
p=(Stud*)malloc(sizeof(Stud));
printf("请重新输入学号:
");scanf("%s",&p->id);
printf("请重新输入姓名:
");scanf("%s",&p->name);
printf("请重新输入性别:
");scanf("%s",&p->sex);
p->next=head->next;
head->next=p;}
voidprint(Stud*head)
{Stud*p=head->next;
printf("学号姓名性别\n");
while(p!
=NULL)
{printf("%-8s",&p->id);
printf("%-15s",&p->name);
printf("%-8s\n",&p->sex);
p=p->next;
}
}
voidmain()
{Stud*head=(Stud*)malloc(sizeof(Stud));
head->next=NULL;
while
(1)
{intch;
printf("\n1增加学生2查询学生信息3删除学生4修改学生信息5显示信息\n");
scanf("%d",&ch);
switch(ch)
{case0:
return;
case1:
add(head);break;
case2:
{charid[20];
printf("输入查询学生的学号:
");
scanf("%s",&id);
search(head,&id);break;}
case3:
{charid[20];
printf("输入删除学生的学号");
scanf("%s",&id);
del(head,&id);break;}
case4:
{charid[20];
printf("输入修改学生的学号");
scanf("%s",&id);
rewrite(head,&id);break;}
case5:
{print(head);break;}
default:
printf("输入错误\n");}
}
}
八、测试情况
程序的测试结果如下:
程序1:
程序2:
程序3:
程序4:
1)输入3个数据后,显示结果如下:
2)查找的数据:
学号:
228,显示结果如下:
3)插入的数据:
434meixunan,显示结果如下:
4)删除的数据:
学号:
228,显示结果如下:
5)修改的数据:
335fangqiannan,显示结果如下:
九、参考文献
1、严蔚敏,《数据结构C语言》,清华大学出版社。
2、谭浩强,《c语言程序设计》,清华大学出版社。
小结
顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。
将表中元素一个接一个的存入一组连续的存储单元中,这种存储结构是顺序结构。
顺序表的存储特点是:
只要确定了起始位置,表中任一元素的地址都可以得到。
单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。
循环链表和单链表的差别仅在于,判别链表中最后一个结点的条件不再是“后继是否为空”,而是“后继是否为头结点”。
循环链表的运算与单链表的运算基本一致。
所不同的有以下几点:
1、在建立一个循环链表时,必须使其最后一个结点的指针指向表头结点,而不是象单链表那样置为NULL。
此种情况还使用于在最后一个结点后插入一个新的结点。
2、在判断是否到表尾时,是判断该结点链域的值是否是表头结点,当链域值等于表头指针时,说明已到表尾。
而非象单链表那样判断链域值是否为NULL。
双向链表:
双向链表中有两条方向不同的链,即每个结点中除next域存放后继结点地址外,还增加一个指向其直接前趋的指针域prior。
它的特点是:
(1)双链表由头指针head惟一确定的;
(2)带头结点的双链表的某些运算变得方便;(3)将头结点和尾结点链接起来,为双向循环链表。
本次课程设计可看成三部分:
第一部分是对线性表的逆置操作;第二部分是运用双向链表有前后两个指针的特点实现往复报数问题;第三部分是运用单链表来实现同学录得建立、修改、删除等操作。
在整个实验中的第二部分有关双向链表的操作,让我头疼不已。
由于它有两个指针域,使得一些基本操作:
建立、插入、删除变得复杂多了。
回头思考这中间所遇到的问题,最根本的原因是对链表的理解和认识还不够深刻,编程能力不足。
通过本次课程设计,我受益很多。
锻炼了我的逻辑思维,和调试程序的能力。
而且还让我知道决定程序成功与否的往往不是程序的整体思路和整体算法,而是细小的书写错误,我在此次课程设计中深有体会。
例如charname[20],我写成了charname;导致我的程序运行的结果出错。
此外,我体验了分工合作,集体编程和个人编程有很大不同,相互间独立而又紧密联系在一起,