实验四树和二叉树的操作.docx
- 文档编号:8010843
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:20
- 大小:301.62KB
实验四树和二叉树的操作.docx
《实验四树和二叉树的操作.docx》由会员分享,可在线阅读,更多相关《实验四树和二叉树的操作.docx(20页珍藏版)》请在冰豆网上搜索。
实验四树和二叉树的操作
实验四树和二叉树的操作
一、实验题目:
用菜单驱动的手法,编写一个完整的程序,生成一棵二叉树,求二叉树的高度,求二叉树的叶子结点数,输出二叉树的所有结点。
二、实验算法描述:
二叉树的生成是指如何在内存中建立二叉树的存储结构。
建立顺序存储结构的问题较简单,这里仅讨论如何建立二叉链表。
要建立二叉链表,就需要按照某种方式输人二叉树的结点及其逻辑信息。
注意到对二叉树遍历时,不仅得到了结点信息,而且由序列中结点的先后关系还可获得一定的逻辑信息,如果这些信息足够,就可根据遍历序列生成相应的二叉树
二叉树的生成方法就是基于遍历序列的,相当于遍历问题的逆问题,即由遍历序列反求二叉树,这需要分析和利用二叉树遍历序列的特点。
在下列两种方法中任选一种。
**以下的
(一)
(二)要编写在一个完整的程序中。
如果你不能编在一个程序中,则可以用两个完整的程序来实现。
(一)用先根序列建立二叉树
二叉树的结点就按相应的遍历过程逐个生成。
类似层次遍历,如果不对遍历序列作些补充,是不能完整反映结点间的逻辑关系的,也就不能得到正确的结果。
补充的方法也是增加虚结点,但这里只需对空指针对应的位置进行补充,而不必补充到完全二叉树的形式。
以先根遍历上图为例,二叉树的先根输入序列为:
ABD@G@@@CE@@FH@@@
其中@表示虚结点,这里不需要结束符。
算法过程为,先生成根结点,再生成左子树,然后是右子树,左右子树的生成采用递归。
在具体作本实验时,还需编写一个主函数调用这个函数来生成二叉树,最后输出二叉树的结点序列。
(二)按完全二叉树的层次顺序,依次输入结点信息来建立二叉链表
这是因为完全三叉树的层次遍历序列中,结点间的序号关系可反映父子关系即逻辑关系。
对一般的二又树,要补充若干个虚结点使其成为完全二叉树后,冉按其层次顺序输入。
例如,仅含3个结点A、B、C的右单支树(见下图2),按完全二叉树的形式输入的结点序列为:
A@B@@@C#,其中@表示虚结点,#表示输入结束。
算法的基本思想是:
依次输入结点信息,若输入的结点不是虚结点,则建立一个新结点:
若新结点是第1个结点,则令其为根结点;否则将新结点作为孩子链接到它的双亲结点上。
如此重复下去,直至输入字符“#”为止。
这里的关键是新结点与其双亲的链接。
由于是按层次自左至右输入结点的,所以先输入的结点,其孩子也必定较先输入。
即结点与其孩子具有先进先出的特点,于是可设置一个队列,保存已输人结点的地址。
这样,队尾是当前正输入的结点,队头是其双亲结点。
当队头结点的两个孩子都输入完毕后,出队,新的队头是下一个要输入孩子的双亲结点。
如此下去,直到输入结束符为止。
双亲与孩子的链接方法是:
若当前输入的结点编号是偶数,则该结点作为左孩子与其双亲链接;否则作为右孩子与其双亲链。
若双亲结点或孩子结点为虚结点,则无需链接。
实验程序如下:
#include
#include
#include
#include
intcmp(constvoid*a,constvoid*b)
{return*(int*)a-*(int*)b;
}
typedefchardatatype;
typedefstructtreenode
{datatypedata;
structtreenode*leftchild,*rightchild;
}treenode,*bitree;
treenode*t;
intcount=0;
//建立二叉树方法1
treenode*creattree_1()
{
treenode*t,*p,*v[100];
inti,j;
datatypee;
t=NULL;
printf("\n请输入初始二叉树各结点的编号和对应的值(如1,a):
");
scanf("%d,%c",&i,&e);
while(i!
=0&&e!
='#')
{p=(treenode*)malloc(sizeof(treenode));
p->data=e;
p->leftchild=NULL;
p->rightchild=NULL;
v[i]=p;
if(i==1)
{t=p;
}
else
{j=i/2;
if(i%2==0)
{v[j]->leftchild=p;
}
else
{v[j]->rightchild=p;
}
}
printf("\n请继续输入(以0,#结束):
");
scanf("%d,%c",&i,&e);
}
return(t);
}
//建立二叉树方法2
treenode*creattree_2()
{
treenode*t;
datatypee;
scanf("%c",&e);
if(e=='#')
{t=NULL;
}
else
{t=(treenode*)malloc(sizeof(treenode));
t->data=e;
t->leftchild=creattree_2();
t->rightchild=creattree_2();
}
return(t);
}
//先序遍历输出二叉树
voidpreorder(treenode*p)
{
if(p)
{printf("%-4c",p->data);
preorder(p->leftchild);
preorder(p->rightchild);
}
}
//中序遍历输出二叉树
voidinorder(treenode*p)
{if(p)
{
inorder(p->leftchild);
printf("%-4c",p->data);
inorder(p->rightchild);
}
}
//后序遍历输出二叉树
voidpostorder(treenode*p)
{if(p)
{
postorder(p->leftchild);
postorder(p->rightchild);
printf("%-4c",p->data);
}
}
//计算二叉树高度
inttreedepth(bitreebt)
{
intlefthight,righthight,max;
if(bt!
=NULL)
{lefthight=treedepth(bt->leftchild);
righthight=treedepth(bt->rightchild);
max=(lefthight>righthight)?
lefthight:
righthight;
return(max+1);
}
else
{return(0);
}
}
//逆时针旋转90度输出二叉树
voidprinttree(bitreebt,intlevel)
{intj;
if(bt)
{
printtree(bt->rightchild,level+1);
for(j=0;j<=6*level;j++)
printf("");
printf("%c\n",bt->data);
printtree(bt->leftchild,level+1);
}
}
//交换二叉树左右子树
voidexchange(bitreebt)
{bitreep;
if(bt)
{
p=bt->leftchild;
bt->leftchild=bt->rightchild;
bt->rightchild=p;
exchange(bt->leftchild);
exchange(bt->rightchild);
}
}
//计算叶结点数
intleafcount(bitreebt)
{if(bt!
=NULL)
{
leafcount(bt->leftchild);
leafcount(bt->rightchild);
if((bt->leftchild==NULL)&&(bt->rightchild==NULL))
{count++;
}
}
return(count);
}
//输出叶结点
voidpaintleaf(bitreebt)
{if(bt!
=NULL)
{
if(bt->leftchild==NULL&&bt->rightchild==NULL)
{
printf("%-4c",bt->data);
}
paintleaf(bt->leftchild);
paintleaf(bt->rightchild);
}
}
//哈夫曼树
inthaffman()
{
inta[100],b[100];
inti,j=0,k,n;
memset(a,0,100);
memset(b,0,100);
printf("请输入构造哈夫曼树的元素个数(正整数):
");
scanf("%d",&n);
printf("\n");
printf("请依次输入各元素权值(以空格间隔,按ENTER键结束):
\n");
for(i=0;i {scanf("%d",&a[i]); } printf("\n"); getchar(); printf("构造哈夫曼树过程: \n\n"); for(i=0;i {qsort(a,n,sizeof(a[0]),cmp); printf("步骤(%d)",i+1); for(k=i;k {printf("%d",a[k]); } printf("\n\n"); b[j++]=a[i]; b[j++]=a[i+1]; a[i+1]=a[i]+a[i+1]; } printf("当前哈夫曼树的所有结点权值为: \n"); for(i=0;i { printf("%-5d",b[i]); } printf("\n\n"); } intmain() { intcommand; charorder; do{ printf("==================简单二叉树操作菜单===================\n"); printf("*1.建立二叉树(按照完全二叉树)*\n"); printf("*2.建立二叉树(模仿先序递归遍历)*\n"); printf("*3.先序递归遍历二叉树*\n"); printf("*4.中序递归遍历二叉树*\n"); printf("*5.后序递归遍历二叉树*\n"); printf("*6.输出二叉树的高度*\n"); printf("*7.输出二叉树的叶结点*\n"); printf("*8.交换二叉树的左右子树*\n"); printf("*9.打印二叉树*\n"); printf("*10.哈夫曼树(最优二叉树)*\n"); printf("*0.退出*\n"); printf("=======================================================\n\n"); printf("请输入指令(0,1,2,3,4,5,6,7,8,9,10): "); scanf("%d",&command); if(command<0||command>10) { getchar(); system("cls"); printf("\n指令输入错误! 请重新输入! \n"); } switch(command) { case1: getchar(); system("cls"); printf("若已构建二叉树,此操作将会清除当前二叉树,继续/退出[Y/N]: "); scanf("%c",&order); if(order=='Y'||order=='y') { t=creattree_1(); if(t) { printf("\n当前二叉树为(逆时针旋转90度): \n"); printtree(t,0); printf("\n"); } else { printf("\n当前二叉树为空! 请先建立二叉树! \n"); } getchar(); break; } else { break; } case2: getchar(); system("cls"); printf("若已构建二叉树,此操作将会清除当前二叉树,继续/退出[Y/N]: "); scanf("%c",&order); if(order=='Y'||order=='y') { printf("\n请输入二叉树按先序递归遍历各结点的值(虚结点以#代替): \n"); fflush(stdin); t=creattree_2(); if(t) { printf("\n当前二叉树为(逆时针旋转90度): \n"); printtree(t,0); printf("\n"); } else { printf("\n当前二叉树为空! 请先建立二叉树! \n"); } getchar(); break; } else { break; } case3: getchar(); system("cls"); if(t) { printf("\n当前二叉树为(逆时针旋转90度): \n"); printtree(t,0); printf("\n"); printf("\n先序递归遍历序列为: \n"); preorder(t); printf("\n"); } else { printf("\n二叉树为空! 请先建立二叉树! \n"); } break; case4: getchar(); system("cls"); if(t) { printf("\n当前二叉树为(逆时针旋转90度): \n"); printtree(t,0); printf("\n"); printf("\n中序递归遍历序列为: \n"); inorder(t); printf("\n"); } else { printf("\n二叉树为空! 请先建立二叉树! \n"); } break; case5: getchar(); system("cls"); if(t) { printf("\n当前二叉树为(逆时针旋转90度): \n"); printtree(t,0); printf("\n"); printf("\n后序递归遍历序列为: \n"); postorder(t); printf("\n"); } else { printf("\n二叉树为空! 请先建立二叉树! \n"); } break; case6: getchar(); system("cls"); if(t) { printf("\n当前二叉树为(逆时针旋转90度): \n"); printtree(t,0); printf("\n"); printf("当前二叉树的高度为: %d\n",treedepth(t)); } else { printf("\n二叉树为空! 请先建立二叉树! \n"); } break; case7: getchar(); system("cls"); if(t) { printf("\n当前二叉树为(逆时针旋转90度): \n"); printtree(t,0); printf("\n"); printf("当前二叉树的叶子结点数为: %d\n\n",leafcount(t)); printf("当前二叉树的叶子结点依次为: \n"); paintleaf(t); printf("\n"); } else { printf("\n二叉树为空! 请先建立二叉树! \n"); } break; case8: getchar(); system("cls"); if(t) { printf("\n当前二叉树为(逆时针旋转90度): \n"); printtree(t,0); printf("\n"); exchange(t); printf("\n交换后的二叉树为: \n"); printtree(t,0); printf("\n"); } else { printf("\n二叉树不存在! 请先建立二叉树! \n"); } break; case9: getchar(); system("cls"); if(t) { printf("\n当前二叉树为(逆时针旋转90度): \n"); printtree(t,0); printf("\n"); } else { printf("\n二叉树不存在! 请先建立二叉树! \n"); } break; case10: getchar(); system("cls"); printf("==========哈夫曼树的建立与输出==========\n\n"); haffman(); break; } if(command==0) { getchar(); system("cls"); printf("再见! \n\n"); break; } printf("\n请按ENTER键返回主菜单! \n"); getchar(); system("cls"); }while(command>=1&&command<=10); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验四 树和二叉树的操作 实验 二叉 操作