杭电软件技术基础实验报告.docx

上传人:b****5 文档编号:3870810 上传时间:2022-11-26 格式:DOCX 页数:28 大小:271.97KB
下载 相关 举报
杭电软件技术基础实验报告.docx_第1页
第1页 / 共28页
杭电软件技术基础实验报告.docx_第2页
第2页 / 共28页
杭电软件技术基础实验报告.docx_第3页
第3页 / 共28页
杭电软件技术基础实验报告.docx_第4页
第4页 / 共28页
杭电软件技术基础实验报告.docx_第5页
第5页 / 共28页
点击查看更多>>
下载资源
资源描述

杭电软件技术基础实验报告.docx

《杭电软件技术基础实验报告.docx》由会员分享,可在线阅读,更多相关《杭电软件技术基础实验报告.docx(28页珍藏版)》请在冰豆网上搜索。

杭电软件技术基础实验报告.docx

杭电软件技术基础实验报告

《软件技术基础》

上机实验报告

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(keydata)

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(keydata)//需删除记录的关键字小于结点的数据;

{//要删除的结点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)/*每循

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1