数据结构实验指导.docx
- 文档编号:11349150
- 上传时间:2023-02-28
- 格式:DOCX
- 页数:33
- 大小:27.38KB
数据结构实验指导.docx
《数据结构实验指导.docx》由会员分享,可在线阅读,更多相关《数据结构实验指导.docx(33页珍藏版)》请在冰豆网上搜索。
数据结构实验指导
实验一:
线性表
一、实验目的与要求
1.熟悉C语言的上机环境,进一步掌握C语言的结构特点。
2.掌握线性表的顺序存储结构的定义及C语言实现。
3.掌握线性表的链式存储结构——单链表的定义及C语言实现。
4.掌握线性表在顺序存储结构即顺序表中的各种基本操作。
5.掌握线性表在链式存储结构——单链表中的各种基本操作。
二、实验预习与准备
1.复习教材相关章节内容。
2.复习C语言中关于结构体与指针的相关内容。
3.认真阅读实验题目,事先写好程序。
三、实验内容和步骤
实验题目1:
实现单链表各种基本运算的算法。
编写一个程序,实现单链表的各种基本运算,以下各功能分别用一个函数来实现,并在此基础上设计一个主函数进行验证各函数的正确性:
(1)初始化单链表L。
(2)输出单链表L。
(3)释放单链表L。
(4)输出单链表L的长度。
(5)判断单链表L是否为空。
(6)输出单链表L的第i个元素的值。
(7)输出元素x的位置(或地址)。
(8)在第i个元素位置上插入值为x的元素。
(9)删除L的第i个元素(或值为x的元素)。
参考程序:
typedefstructnode{
DataTypedata;/*每个元素数据信息*/
structnode*next;/*存放后继元素的地址*/
}LNode,*LinkList;
LinkListCreateList_L(void)
{LNode*tail,*p;intx;
L=(LinkList)malloc(sizeof(LNode);
L->next=NULL;tail=L;//先建立一个带头结点的链表
scanf(“%d”,&x);
while(x!
=-1)/*假设-1作为结束标志*/
{p=(LinkList)malloc(sizeof(LNode));
p->data=x;p->next=NULL;
tail->next=p;//插入到表尾
tail=p;
scanf(“%d”,&x);
}
}
voidDestroy_LinkList(LinkListH)
{/*入口参数:
单链表头指针的地址,出口参数:
无*/
LinkListp;
while(H!
=NULL)/*释放单链表的所有结点*/
{p=H;
H=H->next;
free(p);
}
}
intLength_LinkList(LinkListH)
{/*求单链表表长,入口参数:
单链表头指针,出口参数:
表长,-1表示
单链表不存在。
*/
LinkListp=H;/*p指向头结点*/
intcount=-1;/*H带头结点所以从-1开始*/
while(p)
{/*p所指的是第count+1个结点*/
p=p->next;
count++;
}
return(count);
}
LinkListLocate_LinkList(LinkListH,inti)
{LinkListp;intj;
p=H;j=0;
while(p&&j
{p=p->next;
j++;}
if(j!
=i||!
p)
{printf("参数i错或单链表不存在");
return(NULL);
}/*第i个结点不存在*/
return(p);
}
LinkListLocate_LinkList(LinkListH,DataTypex)
{/*在单链表中查找值为x的结点,入口参数:
单链表指针,检索元素,出口参数:
找到后返回其指针,否则返回NULL*/
LinkListp=H->next;
while(p&&p->data!
=x)
p=p->next;
return(p);
}
intInsert_LinkList(LinkListH,inti,DataTypex)
{/*返回参数:
成功标志,0不成功,1成功*/
LinkListp,q;
p=Locate_LinkList(H,i-1);/*找第i-1个结点地址*/
if(!
p){printf("i有误");
return(0);}
q=(LinkList)malloc(sizeof(LNode));
if(!
q){printf(”申请空间失败”);
return(0);}/*申请空间失败,不能插入*/
q->data=x;
q->next=p->next;/*新结点插入在第i-1个结点的后面*/
p->next=q;
return
(1);/*插入成功,则返回*/
}
intDel_LinkList(LinkListH,inti)
{/*删除单链表H上的第i个结点;返回参数:
0不成功,1成功*/
LinkListp,q;
if(H==null||H->next==null){
printf("空表不能删除");
return(0);}
p=Locate_LinkList(H,i-1);/*找第i-1个结点地址*/
if(p==null||p->next==null){
printf("参数i错");
return(0);}/*第i个结点不存在*/
q=p->next;/*q指向第i个结点*/
p->next=q->next;/*从链表中删除*/
free(q);/*释放*s*/
return
(1);
}
实验题目2:
线性表的应用。
编写一个程序,在线性表的各种基本运算的基础上,完成以下功能:
(1)有一个不带头结点的单链表L(至少有一个结点),其头指针为head。
设计一个算法将L逆置,即最后一个结点变成第一个结点,原来倒数第二个结点变成第二个结点,如此等等。
(2)设计算法分别实现两个集合的交、并、差运算。
参考程序:
voidreverse_LinkList(LinklistH)
{
LinkListp,q;
p=H->next;/*p指向第一个数据结点*/
H->next=NULL;/*将原链表置为空表H*/
while(p){
q=p;
p=p->next;
q->next=H->next;/*将当前结点插到头结点的后面*/
H->next=q;
}/*while*/
}
voidInter_sec(LinklistA,LinklistB)
{/*求集合A和B的交集,入口参数:
指向集合A和B的指针,返回值:
无*/
DataTypex;
Linklistpre,p;
pre=A;p=pre->next;/*刚开始pre指向头结点,p指向第一个链表结点*/
while(p)
{x=p->data;
if(!
Locate_LinkList_Value(B,x))/*集合B中没有x*/
{pre->next=p->next;
free(p);/*删除该结点,考察下一个结点*/
p=pre->next;}
else
{pre=p;
p=p->next;}/*考察下一个结点*/
}
}
voidMerge_sec(LinklistA,LinklistB)
{/*求集合A和B的并集,入口参数:
指向集合A和B的指针,返回值:
无*/
DataTypex;
Linklistp;
p=B->next;/*初始p指向第一结点*/
while(p)
{x=p->data;
if(!
Locate_LinkList_Value(A,x))/*集合A中没有x*/
Insert_LinkList(A,1,x);
/*将集合B中有而集合A中没有的元素加入到集合A中*/
p=p->next;}
}
}
实验题目3:
完善完整的约瑟夫环程序。
参考程序:
intjosephus_LinkList(LinkListjosephus_Link,ints,intm)
{/*返回值:
1表示成功,0表示表中没有元素*/
LinkListp,pre;intcount;/*p指向当前结点,pre指向其前驱结点*/
if(!
josephus_Link)
{printf(“表中无元素”);
return(0);
}
p=josephus_Link;
for(count=1;count
p=p->next;
printf(“输出约瑟夫序列:
”);
while(p!
=p->next)
{/*不是最后一个元素,输出n-1个元素个结点*/
for(count=1;count {pre=p;p=p->next;} printf(“%d\t”,p->data); pre->next=p->next; free(p);p=pre->next; }/*while*/ printf(“%d\t”,p->data);/*输出最后一个元素个结点*/ free(p); return1; } 实验二: 顺序栈的实现 一、实验目的与要求 1、加深理解栈作为一种操作受限的特殊线性表的特殊性所在。 2、掌握栈的基本操作,初始化栈、判栈空、入栈、出栈等运算在两种存储结构上的实现。 二、实验内容和步骤 实验题目1: 实现顺序栈各种基本运算的算法。 编写一个程序,实现顺序栈的如下各种基本运算,并在此基础上设计一个主程序验证其正确性: (1)初始化栈S。 (2)判断栈S是否非空。 (3)进栈。 (4)出栈。 (5)输出栈S的长度。 参考程序: #defineMAXSIZE100 typedefstruct{ DataTypedata[MAXSIZE]; inttop; }SeqStack,*PSeqStack; PSeqStackInit_SeqStack(void) {/*创建一顺序栈,入口参数无,返回一个指向顺 序栈的指针,为零表示分配空间失败*/ PSeqStackS; S=(PSeqStack)malloc(sizeof(SeqStack)); if(S) S->top=-1; returnS; } intEmpty_SeqStack(PSeqStackS) {/*判断栈是否为空,入口参数: 顺序栈,返回值: 1表示为空,0表示非空*/ if(S->top==-1) return1; else return0; } intPush_SeqStack(PSeqStackS,DataTypex) {/*入口参数: 顺序栈,返回值: 1表示入栈成功,0表示失败。 */ if(S->top==MAXSIZE-1)return0;/*栈满不能入栈*/ else{ S->top++;S->data[S->top]=x; return1;} } intPop_SeqStack(PSeqStackS,DataType*x) {/*入口参数: 顺序栈,返回值: 1表示出栈成功,0表示失败。 */ if(Empty_SeqStack(S)) return0;/*栈空不能出栈*/ else{ *x=S->data[S->top];S->top--; return1;} } 实验题目2: 设计一个算法判断一个算术表达式的圆括号是否正确配对。 (提示: 对表达式进行扫描,凡遇“(”就进栈,遇“)”就将栈顶的“(”出栈,表达式扫描完毕,栈应为空。 ) 参考程序: •voidpair(charstr[]) •{PSeqStackS=Init_SeqStack(); •charch,ch1;intk=0; •while((ch=str[k])! =‘\0’) •{if(ch==‘(‘Push_SeqStack(S,ch); •elseif(ch==‘)’) •{if(Empty_SeqStack(s)) •{printf(“error”);return;} •elsePop_SeqStack(S,&ch1); •} •k++;} •if(Empty_SeqSatck(s))printf(“right! ”); •elseprintf(“error”); •} 实验题目3: 设计一个算法将一个数转换成二进制数。 参考程序: typedefintDataType; intconversion(intN,intr) { PSeqStackS;DataTypex;/*定义一个顺序栈*/ if(! r){printf(“基数不能为0”); return(0);} S=Init_SeqStack();/*初始化栈*/ if(! S){printf(“栈初始化失败”); return(0);} while(N){ Push_SeqStack(S,N%r);/*余数入栈*/ N=N/r; }/*商作为被除数继续*/ while(! Empty_SeqStack(S)){ /*直到栈空退出循环*/ Pop_SeqStack(S,&x);/*弹出栈顶元素*/ printf(“%d”,x); }/*输出栈顶元素*/ Destroy_SeqStack(&S);/*销毁栈*/ } 实验三: 队列的实现及应用 一、实验目的与要求 1、加深理解队列作为一种操作受限的特殊线性表的特殊性所在。 2、掌握循环队列的基本操作,初始化队列、判队列空满、入队列、出队列等运算。 二、实验内容和步骤 实验题目1: 实现循环队列各种基本运算的算法。 编写一个程序,实现循环的如下各种基本运算,并在此基础上设计一个主程序验证其正确性: (1)初始化队列Q。 (2)判断队列Q是否非空。 (3)进队列。 (4)出队列。 参考程序: #defineMAXSIZE100/*队列的最大容量*/ typedefstruct{ DataTypedata[MAXSIZE];/*队列的存储空间*/ intfront,rear;/*队头队尾指针*/ }SeqQueue,*PSeqQueue; PSeqQueueInit_SeqQueue() {/*返回值: 新顺序队列指针,null表示失败*/ PSeqQueueQ;Q=(PSeqQueue)malloc(sizeof(SeqQueue)); if(Q) {Q->front=-1;Q->rear=-1;} returnQ; } voidDestroy_SeqQueue(PSeqQueueQ) { if(Q) free(Q); Q=NULL; } intEmpty_SeqQueue(PSeqQueueQ) /*返回值: 1表示为空,0表示非空*/ {if(Q&&Q->front==Q->rear) return (1); else return(0); } intIn_SeqQueue(PSeqQueueQ,DataTypex) {/*返回值: 1表示成功,-1表示队满溢出*/ if((Q->rear+1)%MAXSIZE==Q->front|| Q->front==-1&&Q->rear+1==MAXSIZE) {printf("队满"); return–1;/*队满不能入队*/ } else {Q->rear=(Q->rear+1)%MAXSIZE; Q->data[Q->rear]=x; return1;/*入队完成*/ } } intOut_SeqQueue(PSeqQueueQ,DataType*x) {/*返回值: 1表示成功,-1表示队空,出队的元素保存到*x*/ if(Empty_SeqQueue(Q)){ printf("队空"); return–1;/*队空不能出队*/ } else {Q->front=(Q->front+1)%MAXSIZE; *x=Q->data[Q->front]; return1;/*出队完成*/ } } 实验题目2: 打印杨辉三角的前N行数字。 参考程序: voidYangHui_trangle(intn) { ints=0;inti;intt; PSeqQueuesq=Init_SeqQueue(); In_SeqQueue(sq,1);In_SeqQueue(sq,1); for(i=1;i<=n;i++,s=0) {printf("\n"); for(intk=0;k<=40-4*i;k+=2)printf("");/*输出格式控制*/ In_SeqQueue(sq,0); for(intj=1;j<=i+2;j++) {Out_SeqQueue(sq,&t); In_SeqQueue(sq,s+t); s=t; if(j! =i+2)printf("%4d",s); } } printf("\n"); Destroy_SeqQueue(&sq); } 实验题目3: 设停车场是一个可停放n辆汽车的狭长通道,且只有一个大门可供汽车进出。 汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在车场的最北端),若车场内已停满n辆汽车,则后来的汽车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆车即可开入;当停车场内某辆车要离开时,在它之后时入的车辆必须先退出车场为它让路,待该辆车开出大门外,其他车辆再按原次序进入车场,每辆停放在车场的车在它离开停车场时必须按它停留的时间长短交纳费用。 试为停车场编制按上述要求进行管理的模拟程序。 提示: 以栈模拟停车场,以队列模拟车场外的便道,按照从终端读入的输入数据序列进行模拟管理。 每一组输入数据包括3个数据项: 汽车“到达”或“离开”信息、汽车牌照号码以及到达或离去的时刻。 对每一组输入数据进行操作后的输出信息为: 若是车辆到达,则输出汽车在停车场内或便道上的停车位置;若是车辆离去,则输出汽车在停车场内停留的时间和应交纳的费用(在便道上停留的时间不收费)。 栈以顺序结构实现,队列以链表结构实现。 实验四: 模式匹配 一、实验目的与要求 1.理解字符串的顺序存储的实现。 2.掌握字符串的基本操作,重点掌握模式匹配。 3.深入了解KMP算法的工作原理,掌握next函数的工作原理。 二、实验内容和步骤 实验题目1: 编写程序,不使用标准库函数,实现字符串的以下操作: (1)实现两个字符串拼接的函数strcat(str1,str2) (2)实现字符串拷贝的函数strcpy(str1,str2) (3)实现字符串查找的函数strcstr(str1,str2) (4)实现字符串长度计算的函数strlen(str1,str2) (5)实现在字符串中查找指定字符的函数strchar(str1,c) (6)实现字符串替换的函数strcreplacestr(str1,str2,str3) 实验题目2: 编写一个通讯录管理系统,要求系统完成以下几方面的功能: (1)输入信息 (2)显示信息 (3)以姓名作为关键字进行查找 (4)以姓名作为关键字删除信息 参考程序1: 完善BF模式匹配算法。 intStrIndex_BF(char*s,char*t) {/*从串s的第一个字符开始找首次与串t相等的子串*/ inti=1,j=1; while(i<=s[0]&&j<=t[0]) /*两个串都没有扫描完*/ if(s[i]==t[j]){ i++;j++; }/*继续*/ else{ i=i-j+2; j=1; }/*回溯*/ if(j>t[0]) return(i-t[0]);/*匹配成功,返回存储位置*/ else return–1; } 参考程序2: 完善KMP模式匹配算法。 voidGetNext(char*t,intnext[]) {/*求模式t的next值并存入next数组中*/ inti=1,j=0;next[1]=0; while(i if(j==0||t[i]==t[j]){ ++i;++j; next[i]=j; } elsej=next[j]; } } intStrIndex_KMP(char*s,char*t,intpos) {/*从串s的第pos个字符开始找首次与串t相等的子串*/ inti=pos,j=1; while(i<=s[0]&&j<=t[0])/*都没遇到结束符*/ if(j==0||s[i]==t[j]){ i++;j++; } elsej=next[j];/*回溯*/ if(j>t[0]) returni-t[0]; /*匹配成功,返回存储位置*/ else return–1; } 实验五: 数组的操作及特殊矩阵的压缩存储实现 一、实验目的与要求 1.理解数组在内存中是如何存储和访问时是如何寻址的。 2.掌握用三元组实现特殊矩阵压缩存储的方法和操作实现。 二、实验内容和步骤 实验题目1: 设有一个数组A: array[0…N-1];存放的元素为0-N-1(1 现对数组A的编码定义如下: A[0]的编码为0; A[i]的编码为: 在A[0],A[1],…,A[i-1]中比A[i]的值小的个数(i=1,2,3,…,N-1) 例如A=(4,3,0,5,1,2) , 则数组A的编码B为: B=(0,0,0,3,1,2) 要求: 给出数组A,求解A的编码B; 给出数组A的编码B后,求出A中原数据。 实验题目2: 编程序求一个稀疏的m×n矩阵A的转置矩阵B。 (要求: 稀疏矩阵A和B都用三元组的方式存储和显示出来) 参考程序: tripletable
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 指导
![提示](https://static.bdocx.com/images/bang_tan.gif)