数据结构之二叉树作业
【摘要】:本章着重介绍一种较为抽象的数据结构——树、二叉树。书上使用艰深的语言和算法实现该数据结构让人心碎不已,这次作业将由浅入深,探究一下对于二叉树我们应该掌握哪些要点,哪些是不必过分关注的。
题6.2 一棵度为2的树与一棵二叉树有何区别?
思考:考察树的基本概念和要素。
答:结点拥有的子树数目成为结点的度。度为2的树的含义就是,这棵树的所有结点中,最大的度为2。于是我们能够得到,该树的每个结点最多有2个子结点。看似与二叉树的要求是一样的。但,二叉树的规定除了每个结点的度不能大于2以外,还要求每个结点的子结点要严格规定左右儿子,即使该结点只有一个子结点,也需要规定该子结点是左儿子还是右儿子,显然,对于度为2的普通树是没有这个要求的。归根结底,二叉树和树是两种不同的数据类型,树可以分为无序树和有序树,但无论是否有序,当子结点只有一个时是不区分左右儿子的,这一点是树与二叉树的最大区别。
题6.29 假设一棵二叉树的层序序列为ABCDEFGHIJ和中序序列为DBGEHJACIF。清画出该树。
思考:本题考试对二叉树中序序列的理解和画树。其中层序序列是按照层的顺序一层一层的书写。中序序列是每次都访问当前节点的最终左儿子,然后是该儿子的父亲,再后对右儿子做同样的操作,对每个结点操作的顺序是左儿子>结点自己>右儿子。
答:
如图示。从根结点A开始,找到的第一个左儿子结点是D,然后返回上一层的B,走右儿子分支的第一个左儿子结点是G,然后返回E。E的右儿子已经没有左儿子,于是访问E的右儿子H和H的右儿子J。左半边树访问完毕后,返回根结点A,然后访问右半边树,方法同上,不赘述。
题6-X 假设二叉树如下,请分别写出先序、中序和后序遍历结果,并画出该二叉树对应的森林。
思考:本题继续考察对二叉树遍历方法的掌握和二叉树——森林之间的转换。前者不多说,后者实际上是利用的二叉树和森林采用类似链式存储的关系。二叉树的左指针指向左儿子,右指针指向右儿子。森林/树的左指针指向第一个儿子,右指针指向下一个兄弟。指向的角度去想就可以得到相互的转化。
答:
先序遍历:A B D G C E F H
中序遍历:D G B A E C H F
后序遍历:G D B E H F C A
题 6.23 画出与下列已知序列对应的树T。
树的先根次序访问的序列为:GFKDAIEBCHJ;
树的后根次序访问的序列为:DIAEKFCJHBG。
思考:先根后根即先序后序,这里需要注意的是对应的树而不是二叉树,否则是做不出来的。这道题因为数据规模较小,猜是可以猜出来的,稍微简便的方法便是,将树左右分开,每一步处理都这么做,实际上这也是一个已知树先序后序求树的算法。
题 6.43 请编写一个递归算法,将二叉树中所有结点的左、右子树相互交换。
思考:二叉树采用链式结构存储的话,在创建、遍历的时候都需要使用递归。本题中递归实际上就是创建二叉树和遍历二叉树时用到的。我采用先序遍历的方式创建二叉树,采用后序遍历的方式检索二叉树并做交换。事实上本题的算法很简单:要交换每一个结点的左、右子树,要求每一个结点都不能落下——采用遍历;也要求交换的当前结点的所有子树都已经完成交换——这种要求就只有后序遍历中才满足。因为后序遍历的顺序恰好就是将左右儿子遍历之后再找到他们的父亲结点。所以采用后序遍历,在左右儿子遍历结束后,交换当前结点的左右儿子即可。为了方便大家理解和上机调试,这里贴出百度谷歌搜索不到的原创链式树C语言代码:
#include <stdio.h>
#include <stdlib.h>
struct Bnode
{
char data;
struct Bnode *lchild,*rchild;
};
typedef struct Bnode NODE;
NODE *root,* temp;
char c;
void CreateBiTree(NODE *T)
{
T->data=c;
printf("%c",T->data);
scanf("%c",&c);
if(c==' ')T->lchild=NULL;
else
{
T->lchild=(NODE *) malloc(sizeof(NODE));
CreateBiTree(T->lchild);
}
scanf("%c",&c);
if(c==' ')T->rchild=NULL;
else
{
T->rchild=(NODE *) malloc(sizeof(NODE));
CreateBiTree(T->rchild);
}
}
void PostOrderTraverse(NODE *T)
{
if(T->lchild!=NULL)
PostOrderTraverse(T->lchild);
if(T->rchild!=NULL)
PostOrderTraverse(T->rchild);
printf("%c\n",T->data);
}
void SwapLandR(NODE *T)
{
if(T->lchild!=NULL)
SwapLandR(T->lchild);
if(T->rchild!=NULL)
SwapLandR(T->rchild);
if(T->lchild!=NULL||T->rchild!=NULL)
{
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
}
}
int main()
{
root=(NODE *) malloc(sizeof(NODE));
scanf("%c",&c);
CreateBiTree(root);
printf("\n");
SwapLandR(root);
printf("\n");
PostOrderTraverse(root);
getchar();
getchar();
}