中南大学数据结构实验报告.docx
- 文档编号:9832327
- 上传时间:2023-02-06
- 格式:DOCX
- 页数:40
- 大小:159.09KB
中南大学数据结构实验报告.docx
《中南大学数据结构实验报告.docx》由会员分享,可在线阅读,更多相关《中南大学数据结构实验报告.docx(40页珍藏版)》请在冰豆网上搜索。
中南大学数据结构实验报告
中南大学
数据结构实验报告
实验题目:
(1)单链表的实现
(2)栈和队列
(3)二叉树的遍历(4)查找与排序
学生姓名:
代巍
学生学号:
**********
*******
所在学院:
信息科学与工程学院
专业班级:
信息安全1201班
指导教师评定:
签名:
实验一单链表的实现
一、实验目的
了解线性表的逻辑结构和各种存储表示方法,以及定义在逻辑结构上的各种
基本运算及其在某种存储结构上如何实现这些基本运算。
在熟悉上述内容的基础上,能够针对具体应用问题的要求和性质,选择合适的存储结构设计出相应的有效算法,解决与线性表相关的实际问题
二、实验内容
用C/C++语言编写程序,完成以下功能:
(1)运行时输入数据,创建一个单链表
(2)可在单链表的任意位置插入新结点
(3)可删除单链表的任意一个结点
(4)在单链表中查找结点
(5)输出单链表
三、程序设计的基本思想,原理和算法描述:
(包括程序的结构,数据结构,输入/输出设计,符号名说明等)
用一组地址任意的存储单元存放线性表中的数据元素。
以元素(数据元素的映象) + 指针(指示后继元素存储位置) = 结点(表示数据元素 或 数据元素的映象)
以“结点的序列”表示线性表称作线性链表(单链表)
单链表是指数据接点是单向排列的。
一个单链表结点,其结构类型分为两部分:
(1)、数据域:
用来存储本身数据。
(2)、链域或称为指针域:
用来存储下一个结点地址或者说指向其直接后继的指针。
1、单链表的查找
对单链表进行查找的思路为:
对单链表的结点依次扫描,检测其数据域是否是我们所要查好的值,若是返回该结点的指针,否则返回NULL。
2、单链表的插入
因为在单链表的链域中包含了后继结点的存储地址,所以当我们实现的时候,只要知道该单链表的头指针,即可依次对每个结点的数据域进行检测。
假设在一个单链表中存在2个连续结点p、q(其中p为q的直接前驱),若我们需要在p、q之间插入一个新结点s,那么我们必须先为s分配空间并赋值,然后使p的链域存储s的地址,s的链域存储q的地址即可。
(p->link=s;s->link=q),这样就完成了插入操作。
3、单链表的删除
删除运算思想方法删除运算是将表的第i个结点删去。
具体步骤:
找到 i-1 的存储位置p令p-next指向 i 的直接后继结点释放结点 i 的空间,将其归还给"存储池"。
四、源程序及注释
#include
#include
#include
#include
#include
#defineElemTypeint
//链表类型
typedefstructLNode
{
ElemTypedata;
structLNode*next;
}LNode,*LinkList;
intEmptyList(LinkList&L)
{if(L->next==NULL){
return0;
}
else{return1;}
}
//手动建立一个带头结点的线性链表L
voidSCreateList_L(LinkList&L)
{LinkListl,p;
inti;
ElemTyped;
l=(LinkList)malloc(sizeof(LNode));
L=(LinkList)malloc(sizeof(LNode));//生成头结点
l=L;
L->next=NULL;
cout<<"请依次输入结点值,以0为结束:
"< for(i=1;i=1;){ cin>>d; if(d! =0) { p=(LinkList)malloc(sizeof(LNode));//生成新结点 p->data=d; p->next=l->next;l->next=p;l=l->next; } elsebreak; } if(EmptyList(L))cout<<"生成链表成功! ! "; elsecout<<"链表为空,未生成! ! "; cin.get(); cin.get(); }//SCreate_L //自动建立一个带头结点的线性链表L voidZCreateList_L(LinkList&L,intn) {LinkListl,p; l=(LinkList)malloc(sizeof(LNode)); L=(LinkList)malloc(sizeof(LNode));//生成头结点 l=L; L->next=NULL; srand((unsigned)time(NULL)); for(inti=n;i>0;--i){ p=(LinkList)malloc(sizeof(LNode));//生成新结点 p->data=(rand()%100+1); p->next=l->next;l->next=p;l=l->next; } cout<<"生成链表成功! ! "; cin.get(); cin.get(); }//ZCreate_L //建立一个带头结点的线性链表 LinkListCreateList_L() {charc; intn; LinkListL; cout<<"*********建立线性链表*********"< cout<<"1.手动建立"< cout<<"2.自动建立"< cout<<"******************************"< cin>>c; if(c=='1'){SCreateList_L(L);} elseif(c=='2'){cout<<"请输入链表结点的个数: ";cin>>n;ZCreateList_L(L,n);} else{cout<<"输入错误,请重新输入: "< returnL; cin.get(); cin.get(); } //计算线性链表L中结点的个数 intLengthList(LinkList&L) { LinkListp=L->next; inti=0; while(p) { ++i; p=p->next; } returni; cin.get(); cin.get(); }//LengthList //在线性链表L中第i个结点之前插入新的数据元素e voidListInsert_L(LinkList&L) {inti;ElemTypee; cout<<"第i个结点之前插入新的结点,请输入i: "; cin>>i; while(i<=0||i>LengthList(L)) { cout<<"位置错误,重新输入插入位置: "; cin>>i; } LinkListp,s; p=L;intj=0; while(p&&j if(! p||j>i-1){cout<<"输入错误! ! "; cin.get(); cin.get(); } else{ cout<<"新结点的数据为: "; cin>>e; s=(LinkList)malloc(sizeof(LNode)); s->data=e;s->next=p->next; p->next=s; cout<<"插入成功! ! "; } cin.get(); cin.get(); }//ListInsert_L //删除线性链表L中的第i个结点 voidListDelete_L(LinkList&L) { inti; ElemTypee; cout<<"请输入要删除第i个结点的i值: "; cin>>i; while(i<=0||i>LengthList(L)) { cout<<"位置错误,重新输入删除位置: "; cin>>i; } LinkListp,q; p=L;intj=0; q=(LinkList)malloc(sizeof(LNode)); while(p->next&&j p=p->next; ++j; }//寻找第i个结点 if(! (p->next)||j>i-1){cout<<"删除位置不合理"; cin.get(); cin.get(); } else{ q=p->next; p->next=q->next; e=q->data; cout<<"删除成功! ! "< "< free(q);//删除并释放结点 } cin.get(); cin.get(); }//ListDelete_L //输出线性链表L中的所有数据元素 voidPrintList(LinkList&L) { LinkListp=L->next; cout<<"所有数据如下所示: "< while(p) { cout< p=p->next; } cin.get(); cin.get(); }//PrintList voidSearchList(LinkList&L)//查找某一结点,显示其位置 { inti=0; ElemTypen; cout<<"请输入要找的数据: "; cin>>n; if(L==NULL){cout<<"链表为空! ! ";} LinkListp=L->next; while(p->data! =n&&p->next! =NULL){p=p->next;i=i+1;} if(p->data==n){cout<<"找到了对应的结点,在链表的第"< ";} elsecout<<"链表上找不到相应的的结点! ! "; cin.get(); cin.get(); } voidDestroyList(LinkList&L)//退出系统前,内部做结尾工作 { while(L) { LinkListp; p=L; L=L->next; free(p); } L=NULL; cout<<"线性链表L已销毁! ! "< }//DestroyList intmenu_select()//选择函数 { char*m[7]={"1.建立线性链表", "2.某一结点前插入一个结点", "3.删除一个结点", "4.计算结点个数并输出", "5.查找并显示某一结点位置", "6.输出所有节点", "0.退出系统"}; inti; charc1; do{ system("cls");/*清屏*/ cout<<"\n\n=========链表的基本操作=========\n\n"; for(i=0;i<7;i++) cout< cout<<"\n==================================\n"; cout<<"请选择(1-6,0): "; cin>>c1; }while(c1<'0'||c1>'6'); return(c1-'0'); } voidmain() { LinkListL=NULL; for(;;) { switch(menu_select()) { case1: L=CreateList_L(); system("pause"); break; case2: if(L! =NULL)ListInsert_L(L); else{ cout<<"链表为空,请先建链表! ! "; cin.get(); cin.get(); break; } system("pause"); break; case3: if(L! =NULL)ListDelete_L(L); else{ cout<<"链表为空,请先建链表! ! "; cin.get(); cin.get(); break; } system("pause"); break; case4: if(L! =NULL){inti=LengthList(L);cout<<"结点的个数为: "< cin.get(); cin.get();} else{ cout<<"链表为空,请先建链表! ! "; cin.get(); cin.get(); break; } system("pause"); break; case5: if(L! =NULL)SearchList(L); else{ cout<<"链表为空,请先建链表! ! "; cin.get(); cin.get(); break; } system("pause"); break; case6: if(L! =NULL)PrintList(L); else{ cout<<"链表为空,请先建链表! ! "; cin.get(); cin.get(); break; } system("pause"); break; case0: if(L! =NULL)DestroyList(L); exit(0); } } } 五、实验结果 实验二栈和队列 一、实验目的 了解栈和队列的特性。 掌握栈的顺序表示和实现。 掌握栈的链式表示和实现。 掌握队列的顺序表示和实现。 掌握队列的链式表示和实现。 掌握栈和队列在实际问题中的应用。 二、实验内容 编写一个程序实现顺序栈的各种基本运算,并在此基础上设计一个主程序完成如下功能: 初始化顺序栈,插入元素,删除栈顶元素,取栈顶元素,遍历顺序栈,置空顺序栈。 三、程序设计的基本思想,原理和算法描述 栈的修改时按照先进后出的原则进行的,试验中用到构造空栈,及入栈出栈操作。 队列是一种先进先出的线性表,只允许在表的一端插入,而在另一端删除元素,试验中构造队并且入队出队。 立顺序栈SeqStack,存放测试数据;建立队列SeqQueue存放出栈数据; 建立InitStack、StackEmpty、StackFull、Pop、Push、GetTop函数用作顺序栈的基本操作;建立InitQueue、QEmpty、Qfull、InQueue、OutQueue、ReadFront函数用作队列的基本操作; 建立主函数依次按序对子函数进行操作: InitStack初始化栈→Push压入数据→InitQueue初始化队列→Pop弹出数据→InQueue存入队列→OutQueue出队列→Push压入栈→Pop弹出数据→free清空栈与队列。 在数据的输入与数据的输出时提供必要的提示信息。 四、源程序及其注释 #include #include"stack.h" #include #defineMAXSIZE100 //作用: 对栈进行初始化 //参数: 无 //返回值: SeqStack SeqStackSeqStackInit() { SeqStackS; S.top=-1; returnS; } //作用: 对栈进行判断是否为空 //参数: 传入要判断的栈 //返回值: 返回TRUE为空,返回FLASE为非空 intSeqStackEmpty(SeqStackS) { if(S.top<0) { returnTRUE; } else { returnFLASE; } } //作用: 把S置为空栈 //参数: 传入要操作的栈 //返回值: 无 voidClearStack(SeqStack*S) { while(! SeqStackEmpty(*S)) { S->top--; } printf("\n清空! \n"); } //作用: 把元素x压入栈,使其成为新的栈顶元素 //参数: 传入栈和要输入的数字 //返回值: 无 voidSeqStackPush(SeqStack*S,DataTypex) { S->top++;//要求是先挖坑,再种萝卜 S->data[S->top]=x; } //作用: 出栈 //参数: 要从该栈出来 //返回值: 从栈中出来的数 DataTypeSeqStackPop(SeqStack*S) { DataTypetemp; if(SeqStackEmpty(*S)) { printf("sorry! 为空栈! "); //exit (1); } else { temp=S->data[S->top];//出栈是当前出栈,要求先挖萝卜再填坑 S->top--; printf("\n%d\n",temp); } } //作用: 取栈顶元素 //参数: 要操作的栈 //返回值: 从栈中出来的数 DataTypeSeqStackGetTop(SeqStackS) { DataTypetemp; if(SeqStackEmpty(S)) { printf("sorry! 为空栈! "); //exit (1); } else { temp=S.data[S.top];//出栈是当前出栈,要求先挖萝卜再填坑 printf("\n%d\n",temp); } } //作用输出顺序栈中的元素 //参数: 要操作的栈 //返回值: 从栈中出来的数 voidSeqStackPrint(SeqStackS) { DataTypetemp; SeqStackp; p=S; printf("输出栈中的所有元素: "); while(! SeqStackEmpty(p)) { temp=p.data[p.top];//出栈是当前出栈,要求先挖萝卜再填坑 p.top--; printf("\n%d\n",temp);//当这里位置数据类型怎么办 } } voidmain(void) { intnum; intinput; SeqStackp; p=SeqStackInit(); //这里调用入栈函数,把10,20,30进栈 SeqStackPush(&p,10); SeqStackPush(&p,20); SeqStackPush(&p,30); while (1) { printf("\n\t实验二\n\n"); printf("\n1.入栈"); printf("\n2.栈顶元素弹出"); printf("\n3.取栈顶元素"); printf("\n4.输出顺序栈中的元素"); printf("\n5.清空栈\n"); printf("\t请输入要实现的功能\n"); scanf("%d",&num); switch(num) { case1: printf("\n请输入要入栈的数: \t\t\n"); scanf("%d",&input); SeqStackPush(&p,input); break; case2: SeqStackPop(&p); break; case3: SeqStackGetTop(p); break; case4: SeqStackPrint(p); break; case5: ClearStack(&p); break; } } } 五、实验结果 实验三二叉树的建立和遍历 一、实验目的 1、学会实现二叉树结点结构和对二叉树的基本操作。 2、掌握对二叉树每种操作的具体实现,学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。 二、实验内容 编写程序任意输入二叉树的结点个数和结点值,构造一棵二叉树,采用三种递归遍历算法(前序、中序、后序)对这棵二叉树进行遍历并计算出二叉树的高度。 三、程序设计的基本思想,原理和算法描述 1、数据结构的定义 二叉树是另一种树型结构,它的特点是每个结点至多只有两棵子树,并且二叉树有左右之分,其次序不能任意颠倒。 二叉树的存储结构分为顺序存储和链式存储结构,本次我们主要应用二叉树的二叉链表的方式存储方式,实验中首先必须对二叉树的数据结构进行定义,即定义一个二叉链表,其中其数据成员包括节点的数据、左子树的指针、右子树的指针。 2、二叉树的建立 在实验开始前我们要建立一个以先序形式的二叉树,先序的二叉树就是先访问根结点,然后访问左子树,最后访问右子树的遍历。 3、二叉树的遍历 二叉树的遍历分为先序、中序、后序,需先取遍历的节点的数据存入队列中,然后输出。 4、程序中要的函数的介绍 (1)二叉树的类型定义 (2)定义链式队列类型 (3)初始化链式队列的函数 (4)主函数 四、源程序及注释 #include #include typedefstructBiTNode {chardata; structBiTNode*lchild,*rchild; }BiTNode,*BiTree; voidCreatBiTree(BiTree&T) {//前序法创建二叉树 charch; if((ch=getchar())=='\n') T=NULL; else { T=(BiTNode*)malloc(sizeof(BiTNode)); if(! T) exit (1); T->data=ch; CreatBiTree(T->lchild); CreatBiTree(T->rchild); } } voidPreTravel(BiTree&T) {//前序遍历 if(T) { printf("%c",T->data); PreTravel(T->lchild); PreTravel(T->rchild); } } voidMidTravel(BiTree&T) {//中序遍历 if(T) { MidTravel(T->lchild); printf("%c",T->data); MidTravel(T->rchild); } } voidPostTravel(BiTree&T
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 中南 大学 数据结构 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)