数据结构实验指导书02Word文档格式.docx
《数据结构实验指导书02Word文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构实验指导书02Word文档格式.docx(29页珍藏版)》请在冰豆网上搜索。
参考程序:
//头文件SqList.h的内容如下:
#include<
stdio.h>
malloc.h>
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
#defineOVERFLOW-2
typedefintStatus;
typedefstruct{
ElemType*elem;
StatusInitList_Sq(SqList*L)
L->
elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!
L->
elem)return(OVERFLOW);
length=0;
listsize=LIST_INIT_SIZE;
returnOK;
}
StatusCreatList_Sq(SqList*L,intn)
inti;
printf("
输入%d个整数:
\n"
n);
for(i=0;
i<
n;
i++)
scanf("
\n%d"
&
elem[i]);
//以下是整个源程序(保存在shiyan2_1_1.c文件中):
#include"
SqList.h"
voidmain()
inti,n;
SqLista;
SqList*l=&
a;
if(InitList_Sq(l)=-2)printf("
分配失败\n"
);
\n输入要建立的线性表l的长度n:
"
);
//输入线性表的长度
%d"
n);
l->
length=n;
线性表的长度是:
%d\n"
l->
length);
CreatList_Sq(l,n);
//生成线性表
输出线性表l中的元素值:
"
//输出线性表中的元素
l->
length;
%7d"
getch();
}
[实验2]顺序表的插入
实验内容与要求:
利用前面的实验先建立一个顺序表L={21,23,14,5,56,17,31},然后在第i个位置插入元素68,通过对比插入元素前后的线性表发生的变化,判断插入操作是否正确。
分析:
从插入位置到最后位置的所有元素都要后移一位,使空出的位置插入元素值e。
一般在第i个元素之前(1<
=i<
=n)插入一个新元素时,需要有n-i+1个元素进行移动。
但是,插入的位置是不固定的,当插入位置i=1时,全部元素都得移动,需n次移动,当i=2时,移动n-1个元素,依次类似,当i=n时,仅需移动元素一次。
如图2-2所示。
注意如何取到第i个元素,在插入过程中注意溢出情况以及数组的下标与位序(顺序表中元素的次序)的区别。
参考程序:
//保存在shiyan2_1_2.c文件中
StatusListInsert_Sq(SqList*L,inti,ElemTypee){
//在线性表L中的第i个位置前插入一个值为e的元素
//i的取值范围:
1<
=ListLength_Sq(L)
ElemType*newbase,*q,*p;
if(i<
1||i>
length+1)returnERROR;
//i值不合法
if(L->
length>
=L->
listsize){//当前存储空间已满,增加分配量
newbase=(ElemType*)realloc(L->
elem,
(L->
listsize+LISTINCREMENT)*sizeof(ElemType));
newbase)return(OVERFLOW);
//存储分配失败
elem=newbase;
//新基址
length=+LISTINCREMENT;
//增加存储容量
}//if
q=&
(L->
elem[i-1]);
//q为插入位置
for(p=&
elem[L->
length-1]);
p>
=q;
--p)*(p+1)=*p;
//插入位置及以后的元素右移
*q=e;
//插入e
++L->
//表长增1
}//ListInsert_Sq
{
intn,i,x;
SqList*L,a;
L=&
InitList_Sq(L);
\n输入要建立的线性表L的长度:
CreatList_Sq(L,n);
printf("
\n插入元素之前线性表L的长度是:
%d"
L->
printf("
\n插入元素之前线性表L中的元素是:
%5d"
L->
\n输入要插入元素的位置:
scanf("
i);
\n输入要插入的元素的值:
\n%d"
x);
if(ListInsert_Sq(L,i,x)>
0)
\n插入元素之后线性表L的长度是:
printf("
\n插入元素之后线性表L的元素是:
}//if
else
can'
tinsertthedata!
getch();
[实验3]单链表的建立
建立一个带头结点的单链表,结点的值域为整型数据。
要求将用户输入的数据按尾插入法来建立相应单链表。
为了便于实现各种运算,通常在单链表的第一个结点前增设一个附加结点,称为头结点,它的结构与表结点相同,其数据域可不存储信息,也可存储表长等附加信息,具体见图2_3。
(a)不带头结点
(b)带头结点的单链表
单链表的结点结构除数据域外,还含有一个指针域。
用C语言描述结点结构如下:
typedefstructLNode
ElemTypedata;
//数据域
structLNode*next;
//指针域
}Lnode,*Linklist;
注意结点的建立方法及构造新结点时指针的变化。
构造一个结点需用到C语言的标准函数malloc(),如给指针变量p分配一个结点的地址:
p=(Linklist)malloc(sizeof(LNode));
该语句的功能是申请分配一个LNode类型结点的地址空间,并将首地址存入指针变量p中。
当结点不需要时可以用标准函数free(p)释放结点存储空间,这时p为空值(NULL)。
//保存在头文件LinkList.h
#defineNULL0
typedefstructLNode{
}LNode,*LinkList;
voidCreatList_L(LinkListL,intn)
LinkListp,q;
q=L;
for(i=1;
=n;
{
p=(LinkList)malloc(sizeof(LNode));
输入线性表的第%d个元素:
i);
p->
data);
p->
next=q->
next;
q->
next=p;
q=q->
}
//以下程序保存在文件shiyan2_1_3.c中:
LinkList.h"
LinkListhead,p;
intn;
\n输入要建立链表的长度:
head=(LinkList)malloc(sizeof(LNode));
head->
next=NULL;
CreatList_L(head,n);
\n以head为头指针的链表中的元素:
p=head->
while(p)
%5d"
p->
p=p->
[实验4]单链表的合并
建立两个带头结点的有序单链表La,Lb(单调递增),利用La,Lb的结点空间,将La和Lb合并成一个按元素值递增的有序单链表Lc。
对于单链表的操作必须清楚如何将结点插入到链表中,比如将新结点x插入到结点a和b之间,插入结点的指针变化如图2-4所示。
程序需要3个指针:
pa,pb,pc,其中pa,pb分别指向La表、Lb表的首结点,用pa遍历La表,pb遍历Lb表,pc指向合并后的新表的最后一个结点(即尾结点),pc的初值指向La表的头结点。
合并的思想是:
先利用实验3的内容建立好两个链表La表和Lb表,然后依次扫描La和Lb中的元素,比较当前元素的值,将较小者链到*pc之后,如此重复直到La或Lb结束为止,再将另一个链表余下的内容链到pc所指的结点之后。
//以下是程序保存在shiyan2_1_4.c文件中
LinkList.h"
voidMergeList_L(LinkListLa,LinkListLb,LinkListLc)
LinkListpa,pb,pc;
pa=La->
pb=Lb->
pc=Lc;
while(pa&
&
pb)
if(pa->
data>
pb->
data)
pc->
next=pb;
pc=pb;
pb=pb->
else
next=pa;
pc=pa;
pa=pa->
next=pa?
pa:
pb;
free(Lb);
LinkListLa,Lb,Lc,p;
intn1,n2;
La=(LinkList)malloc(sizeof(LNode));
La->
Lb=(LinkList)malloc(sizeof(LNode));
Lb->
Lc=NULL;
\n请输入要建立的链表La的长度:
n1);
CreatList_L(La,n1);
\n请输入要建立的链表Lb的长度"
n2);
CreatList_L(Lb,n2);
p=La->
\n链表La中的元素:
while(p)
p=Lb->
\n链表Lb中的元素:
MergeList_L(La,Lb,Lc);
p=Lc->
\n输出由链表La和Lb归并得到的链表Lc中的元素:
%d"
[实验5]删除单链表中的重复值
编写算法实现将单链表L中值重复的结点删除,使所得结果表中各结点值均不相同。
本题涉及到单链表中关于值的查找算法,从头结点开始,活动指针p沿着单链表向后扫描,寻找某个给定值。
首先建立一个单链表,令p指针指向所建单链表的第一个结点,令q指向p的后继结点,q沿着链表向右(向后)扫描,若找到与p所指结点值相同的结点,则将其删除,继续处理,直到q为空;
然后令p移到下一个结点(即直接后继结点),q依然指向p的后继结点,重复同样的处理。
显然此题需要用到双重循环。
//以下程序保存在shiyan2_1_5.c
//DeleteSameNode函数用来删除链表中重复的结点
voidDeleteSameNode(LinkListh)
LinkListp,q,s
p=h->
s=p;
while(p!
=NULL)
q=p->
while(q!
if(q->
data!
=p->
{
s=q;
//s为q的直接前趋指针,即s紧跟着q向右移动。
q=q->
}//if
s->
//此时q所指向的结点为待删除结点
free(q);
q=s->
//q指向后继结点,继续寻找与p所指结点值相同的结点。
}//else
}//while(q!
p=p->
s=p;
}//while(p!
//OutPut函数用来输出单链表的内容
voidOutPut(LinkListh)
LinkListp;
p=h->
%5"
p=p->
}//while
LinkListhead;
intn;
head=(LinkList)malloc(sizeof(LNode));
head->
请输入要建立的链表的长度:
\n"
CreatList(head,n);
链表中的元素是:
output(head);
删除链表中结点的重复值!
DeleteSameNode(head);
OutPut(head);
//输出经过处理后的单链表,此时单链表中的值应该唯一。
[实验6]单循环链表的逆置
将一个已知的单循环链表进行逆置运算,如(a1,a2,a3,…,an)变为(an,an-1,…,a2,a1)。
对于单链表而言,最后一个结点的指针域是空指针,如果将该链表头指针置入该指针域,则使得链表头尾结点相连,就构成了单循环链表。
对于单链表只能从头结点开始遍历整个链表,而对于单循环链表则可以从表中任意结点开始遍历整个链表。
所谓链表的逆置运算(或称为逆转运算)是指在不增加新结点的前提下,依次改变数据元素的逻辑关系,使得线性表(a1,a2,a3,…,an)成为(an,an-1,…,a2,a1)。
本题采用的算法是:
先建立一个带头结点的单循环链表,从头到尾扫描单链表L,把p作为活动指针,沿着链表向前移动,q作为p前趋结点,r作为q的前趋结点。
其中,q的next值为r,r的初值置为head。
//头文件LNode.h的内容:
#include<
ElemTypedata;
structLNode*next;
}LNode,*LinkList;
//以下是主程序保存在shiyan2_1_6.c中
#include“LNode.h”
//输出循环链表的信息
voidOutPut(LinkListhead)
p=head->
while(p!
=head)
//建立单循环链表
voidCreat(LinkListh,intn)
intk;
LNode*r,*p;
r=h;
for(k=1;
k<
k++)
printf(“输入第%d个结点的数值:
”,k);
p=(LNode*)malloc(sizeof(LNode));
scanf(“%d”,&
next=h;
r->
r=p;
//逆置函数
voidInvert(LinkListh)
LinkListp,q,r;
q=h;
=h)
r=q;
q=p;
q->
next=r;
h->
next=q;
\n输入所建立的循环链表的结点个数:
head=(LNode*)malloc(sizeof(LNode));
next=head;
Creat(head,n);
输出建立的单循环链表:
\n现在进行逆置!
Invert(head);
\n输出进行逆置运算后的单循环链表的结点信息:
2.4提高实验
[实验1]学生成绩管理
学生成绩管理是学校教务管理的重要组成部分,其处理信息量很大,本实验是对学生的成绩管理作一个简单的模拟,用菜单选择操作方式完成下列功能:
①登录学生成绩;
②查询学生成绩;
③插入学生成绩;
④删除学生成绩
本实验涉及单链表的各种操作,包括单链表的建立、结点的查找、插入、删除等基本运算。
链表中插入结点的指针变化见图2-4所示,删除p所指结点的指针变化见图2-5所示。
首先建立学生成绩单链表,每条记录由学号、姓名与成绩组成,即链表中每个结点由4个域组成,分别为:
学号、姓名、成绩、存放下一个结点地址的next域。
然后将要求完成的四项功能写成四个函数,登记学生成绩对应建立学生单链表的功能,后三个功能分别对应单链表的查询、插入与删除三大基本操作。
该系统中的数据采用线性表中的链式存储结构即单链表来存储,用结构体类型定义每个学生记录,这样单链表中每个结点的结构可描述为:
#defineMAXLEN100
typedefstructNode
intnum;
//学号
charname[MAXLEN];
//姓名
floatscore;
//成绩
structNode*next;
}Node;
参考程序
//头文件hh.h的内容
stdlib.h>
#defineMAXLEN100
intnum;
charn