杭电软件技术基础实验报告.docx
- 文档编号:3870810
- 上传时间:2022-11-26
- 格式:DOCX
- 页数:28
- 大小:271.97KB
杭电软件技术基础实验报告.docx
《杭电软件技术基础实验报告.docx》由会员分享,可在线阅读,更多相关《杭电软件技术基础实验报告.docx(28页珍藏版)》请在冰豆网上搜索。
杭电软件技术基础实验报告
《软件技术基础》
上机实验报告
2018至2019学年,第1学期
学生姓名:
***
班级:
***
学号:
***
授课教师:
***
指导教师:
***
报告完成时间:
2018年12月9日
实验一:
链式二叉排序树的创建和遍历
一.实验目的和要求
1.加深理解数据结构的目的和概念,以及逻辑结构和物理结构的关系;
2.练习数据结构操作算法的编程实现;
3.练习链表的程序设计,掌握二叉链表的设计技术;
4.练习递归函数的设计方法;
5.巩固二叉排序树的概念;
6.熟悉软件功能的分析设计方法。
二.功能分析与设计
利用C或C++,设计程序,定义二叉链表,存储二叉排序树,声明并定义相应的函数,实现链式二叉排序树的下列操作:
1.输入数据个数DataCount(要求在10和20之间)和数据最大值MaxData(在50和100之间)。
算法实现:
该任务需要限制输入的DataCount在10和20之间,MaxData在50和100之间,只有当两者均满足要求时,程序才会向下执行。
若不满足时,会提示“输入不正确,请重新输入!
”,并继续输入DataCount和MaxData,直至满足要求。
这里用while
(1)死循环,不得到正确输入不退出。
部分代码如下:
while
(1)
{
printf("请输入DataCount:
");
scanf("%d",&DataCount);
printf("请输入Maxdata:
");
scanf("%d",&Maxdata);
if(DataCount>=10&&DataCount<=20&&Maxdata>=50&&Maxdata<=100)break;
printf("输入不正确,请重新输入!
\n");
fflush(stdin);//清空输入
}
2.在0和MaxData之间,随机产生DataCount个不重复的整数,按产生先后顺序形成一个数据序列,并输出该序列。
算法实现:
因为输入的DataCount具有随机性,数组的长度无法确定,因此想到要申请分配动态数组。
这里需要在0和MaxData之间,随机产生DataCount个不重复的整数,使用c语言中的rand语句,生成一组随机数,并赋值给数组。
要保证不重复,引入下表j,若两数相等,则i自减,继续产生数据。
部分代码如下:
if((arr=(int*)malloc(DataCount*sizeof(int)))==NULL)//申请动态数组
{
printf("分配内存空间失败,程序退出!
");
return0;
}
for(i=0;i { arr[i]=rand()%(Maxdata+1); for(j=0;j if(arr[i]==arr[j]) i--; } printf("输出不重复的数据序列: \n"); for(i=0;i printf("%d\t",arr[i]); 3.利用上述数据序列,创建一个二叉排序树。 算法实现: 首先需要定义节点数据结构,然后根据二叉排序树的特点(左子树节点值小于根节点值,右子树节点值大于等于根节点值),定义插入二叉排序树的insertTree函数,最后定义Creatree函数,并在其中调用insertTree函数,实现了二叉排序树的创建。 部分代码如下: voidinsertTree(Tnode**r,intdata){//插入二叉排序树 if(*r==NULL){//如果树为空,则建树 *r=(Tnode*)malloc(sizeof(Tnode)); (*r)->data=data; (*r)->lchild=NULL; (*r)->rchild=NULL; } elseif(data<(*r)->data)//当前值小于根结点,建左子树 insertTree(&((*r)->lchild),data); elseif(data>(*r)->data)//当前值大于根结点,建右子树 insertTree(&((*r)->rchild),data); } voidCreatree(Tnode**r,inta[],intn){//调用插入函数,实现二叉排序树的创建 inti; for(i=0;i insertTree(&(*r),a[i]); } 4.设计函数,统计该二叉树的高度。 算法实现: 二叉树的高度为二叉树中节点层次的最大值,因此需要分别遍历左、右子树,并求高度。 二叉树的高度为左子树高度、右子树高度中较大的那个。 部分代码如下: intGetHeight(Tnode*r){//定义统计二叉树的高度的函数 inthl,hr,max; if(r! =NULL){ hl=GetHeight(r->lchild);//求左子树高度 hr=GetHeight(r->rchild);//求右子树高度 max=hl>hr? hl: hr; return(max+1); } elsereturn0; } 5.设计函数,输出该二叉树的叶子节点。 算法实现: 当节点的左右子树同时为空时,即为叶子结点。 对二叉树进行遍历,判断被访问的节点是否为叶子节点,若是,将叶子节点对应的数值输出。 部分代码如下: if(r==0)return; elseif(r->lchild==NULL&&r->rchild==NULL)//节点的左右子树同时为空,即为叶子 printf("%d",r->data); outleaf(r->lchild); outleaf(r->rchild); } 6.设计中序遍历函数,遍历该二叉排序树,输出遍历序列,验证创建的二叉排序树是否正确。 算法实现: 首先按中序遍历的顺序递归左子树,然后访问根节点,最后按中序遍历的顺序递归遍历右子树,即可设计中序遍历函数。 由于二叉排序树的中序遍历结果应为从小到大排序,所以只需观察中序遍历序列,即可验证正确性。 部分代码如下: voidinorder(Tnode*r){//定义实现中序遍历的函数 if(r){ inorder(r->lchild); printf("%d",r->data); inorder(r->rchild); } } 三.算法流程图 根据上述功能的分析,设计出本实验的算法流程图如下所示: 图1算法流程图 四.程序源代码 #include #include #include typedefstructnode{//节点数据类型 intdata; structnode*lchild,*rchild; }Tnode; voidinsertTree(Tnode**r,intdata){//插入二叉排序树 if(*r==NULL){//如果树为空,则建树 *r=(Tnode*)malloc(sizeof(Tnode)); (*r)->data=data; (*r)->lchild=NULL; (*r)->rchild=NULL; } elseif(data<(*r)->data)//当前值小于根结点,建左子树 insertTree(&((*r)->lchild),data); elseif(data>(*r)->data)//当前值大于根结点,建右子树 insertTree(&((*r)->rchild),data); } voidCreatree(Tnode**r,inta[],intn){//调用插入函数,实现二叉排序树的创建 inti; for(i=0;i insertTree(&(*r),a[i]); } intGetHeight(Tnode*r){//定义统计二叉树的高度的函数 inthl,hr,max; if(r! =NULL){ hl=GetHeight(r->lchild);//求左子树高度 hr=GetHeight(r->rchild);//求右子树高度 max=hl>hr? hl: hr; return(max+1); } elsereturn0; } voidoutleaf(Tnode*r){//定义输出二叉树的叶子节点的函数 if(r==0)return; elseif(r->lchild==NULL&&r->rchild==NULL)//节点的左右子树同时为空,即为叶子 printf("%d",r->data); outleaf(r->lchild); outleaf(r->rchild); } voidinorder(Tnode*r){//定义实现中序遍历的函数 if(r){ inorder(r->lchild); printf("%d",r->data); inorder(r->rchild); } } intmain() { srand(time(NULL)); Tnode*r=NULL; intDataCount,Maxdata,i,j; int*arr; while (1)//死循环,不得到正确输入不退出 { printf("请输入DataCount: "); scanf("%d",&DataCount); printf("请输入Maxdata: "); scanf("%d",&Maxdata); if(DataCount>=10&&DataCount<=20&&Maxdata>=50&&Maxdata<=100)break; printf("输入不正确,请重新输入! \n"); fflush(stdin);//清空输入 } if((arr=(int*)malloc(DataCount*sizeof(int)))==NULL)//申请动态数组 { printf("分配内存空间失败,程序退出! "); return0; } for(i=0;i arr[i]=rand()%(Maxdata+1); for(j=0;j if(arr[i]==arr[j]) i--; } printf("输出不重复的数据序列: \n"); for(i=0;i printf("%d\t",arr[i]); Creatree(&r,arr,i); printf("输出二叉树的高度: \n"); printf("%d\n",GetHeight(r));//输出二叉树的高度 printf("输出二叉树的叶子节点: \n"); outleaf(r);//输出二叉树的叶子节点 printf("\n"); printf("输出中序遍历序列: \n"); inorder(r);//输出中序遍历序列 printf("\n"); free(arr);//使用完后要释放所申请的空间 return0; } 五.调试方法和调试过程 调试过程中,出现了大大小小的问题: 第一次编译,很多错误,仔细检查后发现是头文件缺失造成的。 修改后,错误明显少多了。 还有语句后面忘记加分号或者中英文没有区分,导致了一些编译错误。 耐心的调试后,所有的错误都解决了。 六.程序运行主要截图 1.输入DataCount和MaxData,若输入的两个值再指定的范围内(即 ),则程序向下执行;若不再指定范围内,则提示重新输入。 运行窗口如下: 图2输入正确的数值 2.创建二叉树,输出高度、叶子节点,对二叉排序树进行中序遍历。 运行窗口如下: 图3高度、叶子节点、中序遍历 七.总结与体会 这次上机练习,感受之一就是手生,好长时间不用c语言编程,有一种陌生感,所以这次练习调试程序过程中也遇到了大大小小的困难,不过通过自己网上查找资料都解决了。 对一些c语言编程用法加深了理解,比如动态分配数组,生成随机数,结构体,递归等内容,现在能够熟练应用,并在实际问题中实现。 其次,深刻认识了二叉排序树的结构,运用递归定义函数实现了二叉树的构建,求解树的高度、叶子节点等内容,有关二叉树的三种遍历方法也清楚了具体的遍历顺序。 实验二: 链式二叉排序树的查找和删除 一.实验目的和要求 1.加深理解数据结构的目的和概念,以及逻辑结构和物理结构的关系; 2.锻炼较为复杂数据结构算法的设计和编程实现; 3.练习链表的程序设计,掌握二叉链表的设计技术; 4.熟悉图结构的物理存储和应用的编程方法; 5.熟悉软件功能的分析设计方法和测试方法。 二.功能分析与设计 1.创建一棵二叉排序树(以下称为源二叉树)。 算法实现: 创建方法与实验一相同,这里不做叙述。 2.从源二叉树拷贝一个二叉树(以下称为二叉树副本)。 算法实现: 首先判断二叉树是否为空,若二叉数为空,则没有任何操作;若二叉树不为空,开辟内存空间,依次复制根节点,左子树和右子树,至此完成二叉树的复制。 部分代码如下: Tnode*mycopy(Tnode*r){//二叉树的复制 if(! r)returnNULL; Tnode*copyr=(Tnode*)malloc(sizeof(Tnode)); copyr->data=r->data; copyr->lchild=mycopy(r->lchild); copyr->rchild=mycopy(r->rchild); returncopyr; }; 3.通过键盘输入数据,指定查找的目标二叉树(源二叉树和二叉树副本),在目标二叉树中查找是否存在该数据,若存在,则输出提示以及该数据节点的地址,若不存在,则输出提示。 算法实现: 首先,通过定义变量k,选择查找哪一棵树。 k=1,表明在源二叉树中查找;k=2,表明在二叉树副本中查找;k=其他值,提示“选择错误”,并且重新输入,直到查找的二叉树为源二叉树或副本。 因为需要在目标二叉树中查找是否存在某数据,所以要定义一个查找节点的函数。 这里编写了search函数,首先判断根节点数值与要查找数值是否相等,若等,则输出找到;若不等,则对左子树、右子树递归调用上面函数。 部分代码如下: Tnode*search(Tnode*r,intkey){//在二叉排序树中查找值为key的节点 if(r==NULL) { printf("没有找到! "); returnNULL; } elseif(r! =NULL&&key==r->data){ printf("Findit! \n"); printf("输出数据在内存中的地址: "); printf("%d",&r); returnr; } elseif(key returnsearch(r->lchild,key); elseif(key>r->data) returnsearch(r->rchild,key); } 4.删除数据操作: 通过键盘输入数据;如果二叉树副本中存在该数据,则从二叉树副本中删除该数据节点,输出提示,并输出源二叉树和删除操作后的二叉树副本的中序遍历结果和高度;如果二叉树副本中不存在该数据,输出提示,并输出提示源二叉树中是否存在该数据节点以及节点地址。 算法实现: 对二叉树的节点进行删除操作,要分下面三种情况: 1)当删除的节点是叶子节点时,只要把删除节点的父节点对应的指针指向NULL即可,然后释放掉删除节点的空间。 2)当删除的节点只有一个子节点(左子树或右子树),把删除节点的父节点中对应的指针指向删除节点的子节点即可。 然后释放掉删除节点的空间; 3)当删除的节点左右子树都有,这种情况下,必须要找到一个替代删除节点的替代节点,并且保证二叉树的排序性。 根据二叉树的排序性,可知替代节点的键值必须最接近删除节点键值。 比删除节点键值小的所有键值中最大那个,或者是比删除节点键值大的所有键值中最小的那个,是符合要求的。 这两个键值所在的节点分别在删除节点的左子树中最右边的节点,删除节点右子树中最左边的节点; 部分代码如下: //获得其父节点 Tnode*getFather(Tnode*r,Tnode*s) { Tnode*sf; if(r==NULL||r==s) sf=NULL; else{ if(s==r->lchild||s==r->rchild) sf=r; elseif(s->data>r->data) sf=getFather(r->rchild,s); else sf=getFather(r->lchild,s); } returnsf; } //二叉树删除 voidDeleteNode(Tnode*r,intkey) { Tnode*L,*LL;//在删除左右子树都有的结点时使用; Tnode*p=r; Tnode*parent=r; intchild=0;//0表示左子树,1表示右子树; if(! r)//如果排序树为空,则退出; return; while(p)//二叉排序树有效; { if(p->data==key) { if(! p->lchild&&! p->rchild)//叶结点(左右子树都为空); { if(p==r)//被删除的结点只有根结点; free(p); elseif(child==0) { parent->lchild=NULL;//设置父结点左子树为空; free(p);//释放结点空间; } else//父结点为右子树; { parent->rchild=NULL;//设置父结点右子树为空; free(p);//释放结点空间; } } elseif(! p->lchild)//左子树为空,右子树不为空; { if(child==0)//是父结点的左子树; parent->lchild=p->rchild; else//是父结点的右子树; parent->rchild=p->rchild; free(p);//释放被删除的结点; } elseif(! p->rchild)//右子树为空,左子树不为空; { if(child==0)//是父结点的左子树; parent->lchild=p->lchild; else//是父结点的右子树; parent->rchild=p->lchild; free(p);//释放被删除的结点; } else { LL=p;//保存左子树的结点; L=p->rchild;//从当前结点的右子树进行查找; if(L->lchild)//左子树不为空; { LL=L; L=L->lchild;//查找左子树; p->data=L->data;//将左子树的数据保存到被删除结点; LL->lchild=L->lchild;//设置父结点的左子树指针为空; for(;L->lchild;L=L->lchild); L->lchild=p->lchild; p->lchild=NULL; } else { p->data=L->data; LL->rchild=L->rchild; } } p=NULL; } elseif(key {//要删除的结点p是parent的左子树; child=0;//标记在当前结点左子树; parent=p;//保存当前结点作为父结点; p=p->lchild;//查找左子树; } else//需删除记录的关键字大于结点的数据; {//要删除的结点p是parent的右子树; child=1;//标记在当前结点右子树查找; parent=p;//保存当前结点作为父结点; p=p->rchild;//查找右子树; } } } 5.将源二叉树视为一个图数据结构,编写函数实现该图的邻接表存储(注意程序需确保该操作不会被重复操作)。 算法实现: 首先对每个顶点 建立一个单链表,这个单链表由邻接于 的所有顶点构成。 这个表头节点通常以顺序存储结构存储,以便随机访问任一顶点的链表。 6.编写函数实现该图的拓扑排序,并输出拓扑序列。 算法实现: 首先在有向图中选取一个没有前驱的顶点(即入度为0的顶点),并输出该顶点;然后从有向图中删除该顶点和以它为尾的所有弧;重复前两步,直到全部顶点都被输出,或者有向图中没有入度为0的顶点为止。 部分代码如下: voidTopoSort(adjlistGL,intn) { inti,j,k,top,m=0;/*m用来统计拓扑序列中的顶点数*/ structedgenode*p;/*单链表*/ int*d=(int*)malloc(n*sizeof(int));/*定义存储图中每个顶点入度的一维整形数组d*/ for(i=0;i d[i]=0;/*初始化数组*/ for(i=0;i { p=GL[i]; while(p! =NULL) { j=p->adjvex; d[j]++; p=p->next; } } top=-1;/*初始化用于链接入度为0的元素的栈的栈顶指针为-1*/ for(i=0;i if(d[i]==0) { d[i]=top; top=i; } while(top! =-1)/*每循
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 软件技术 基础 实验 报告