实验树和二叉树操作.docx
- 文档编号:23863799
- 上传时间:2023-05-21
- 格式:DOCX
- 页数:23
- 大小:301.35KB
实验树和二叉树操作.docx
《实验树和二叉树操作.docx》由会员分享,可在线阅读,更多相关《实验树和二叉树操作.docx(23页珍藏版)》请在冰豆网上搜索。
实验树和二叉树操作
实验四树和二叉树的操作
一、实验题目:
用菜单驱动的手法,编写一个完整的程序,生成一棵二叉树,求二叉树的高度,求二叉树的叶子结点数,输出二叉树的所有结点。
二、实验算法描述:
二叉树的生成是指如何在内存中建立二叉树的存储结构。
建立顺序存储结构的问题较简单,这里仅讨论如何建立二叉链表。
要建立二叉链表,就需要按照某种方式输人二叉树的结点及其逻辑信息。
注意到对二叉树遍历时,不仅得到了结点信息,而且由序列中结点的先后关系还可获得一定的逻辑信息,如果这些信息足够,就可根据遍历序列生成相应的二叉树
二叉树的生成方法就是基于遍历序列的,相当于遍历问题的逆问题,即由遍历序列反求二叉树,这需要分析和利用二叉树遍历序列的特点。
在下列两种方法中任选一种。
**以下的<一)<二)要编写在一个完整的程序中。
如果你不能编在一个程序中,则可以用两个完整的程序来实现。
<一)用先根序列建立二叉树
二叉树的结点就按相应的遍历过程逐个生成。
类似层次遍历,如果不对遍历序列作些补充,是不能完整反映结点间的逻辑关系的,也就不能得到正确的结果。
补充的方法也是增加虚结点,但这里只需对空指针对应的位置进行补充,而不必补充到完全二叉树的形式。
以先根遍历上图为例,二叉树的先根输入序列为:
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 i++> {scanf("%d",&a[i]>。 } printf("\n">。 getchar(>。 printf("构造哈夫曼树过程: \n\n">。 for(i=0。 i i++> {qsort(a,n,sizeof(a[0]>,cmp>。 printf("步骤<%d)",i+1>。 for(k=i。 k 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 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文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 二叉 操作