知识大全 数据结构第六章(树)习题答案(上)
Posted 结点
篇首语:案头见蠹鱼,犹胜凡俦侣。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 数据结构第六章(树)习题答案(上)相关的知识,希望对你有一定的参考价值。
二 算法设计题
二叉树的遍历算法可写为通用形式 例如通用的中序遍历为
void Inorder(BinTree T void(* visit)(DataType x))
if (T)
Inorder(T >lchild Visit);//遍历左子树
Visit(T >data);//通过函数指针调用它所指的函数来访问结点
Inorder(T >rchild Visit);//遍历右子树
其中Visit是一个函数指针 它指向形如void f(DataType x)的函数 因此我们可以将访问结点的操作写在函数f中通过调用语句Inorder(root f)将f的地址传递给Visit 来执行遍历操作 请写一个打印结点数据的函数 通过调用上述算法来完成书中 节的中序遍历
解 这个函数如下
void PrintNode(BinTree T)
printf( %c T >data);
为了验证这个函数是否正确 要先建立一棵二叉树 然后调用这个中序遍历算法 //定义二叉树链式存储结构
typedef char DataType;//定义DataType类型
typedef struct node
DataType data;
struct node *lchild *rchild;//左右孩子子树
BinTNode; //结点类型 typedef BinTNode *BinTree ;//二叉树类型 #include
#include
void CreatBinTree(BinTree *T)//输入序列是先序序列
//构造二叉链表 T是指向根的指针 故修改了*T就修改了实参
char ch;
if ((ch=getchar())== )
*T=NULL;
else //读入非空格
*T=(BinTNode *)malloc(sizeof(BinTNode));//生成结点
(*T) >data=ch;
CreatBinTree(&(*T) >lchild); //构造左子树
CreatBinTree(&(*T) >rchild); //构造右子树
//
void PrintNode(DataType x)
//题目要求的打印函数
printf( %c x);
//
void Inorder(BinTree T void(* Visit)(DataType x))
if(T)
Inorder(T >lchild Visit);//遍历左子树
Visit(T >data); //通过函数指针调用它所指的函数访问结点
Inorder(T >rchild Visit);//遍历右子树
void main()
//现在开始测试啦 BinTree root; //定义一个根结点
CreatBinTree(&root); //建立二叉链表
printf( \\n );
Inorder(root PrintNode);//调用函数 注意传递的是函数名(它就是地址)
printf( \\n );
//运行时请输入 ab c (注意b后和c后面各两个空格)再回车 可生成一个以a为根的两片叶子的二叉树 看看打印的结果对不对?
以二叉链表为存储结构 分别写出求二叉树结点总数及叶子总数的算法
解 利用中序遍历 我们很容易地就能找到这个算法每访问一次非空结点就给变量nodes加上 ; 每访问到一个其左右子树皆空的结点就给变量leaves加上 最后就得到结果了
完整程序如下所示 //定义二叉树链式存储结构等内容 为方便起见我们将这一段内容存为bintree h文件 以后只在程序中加入这个头文件就是了 // bintree h 文件开始 typedef char DataType;//定义DataType类型
typedef struct node
DataType data;
struct node *lchild *rchild;//左右孩子子树
BinTNode; //结点类型 typedef BinTNode *BinTree ;//二叉树类型 #include
#include
void CreatBinTree(BinTree *T)
//构造二叉链表 注意:输入序列是先序序列
char ch;
if ((ch=getchar())== )
*T=NULL;
else //读入非空格
*T=(BinTNode *)malloc(sizeof(BinTNode));//生成结点
(*T) >data=ch;
CreatBinTree(&(*T) >lchild); //构造左子树
CreatBinTree(&(*T) >rchild); //构造右子树
// 文件结束 // 以下两个函数为题目要求算法 int Node(BinTree T)
//算结点数
int static nodes= ;//静态变量保留每次递归调用后的值
if(T)
//使用中序遍历
Node(T >lchild); //遍历左子树
nodes++; //结点数加
Node(T >rchild); //遍历右子树
return nodes;
int Leaf(BinTree T)
//算叶子数
int static leaves= ;//静态变量保证其值不会随递归调用而消失
if(T)
//使用中序遍历
Leaf(T >lchild); //遍历左子树
if(!(T >lchild||T >rchild))//左右孩子均为空
leaves++; //叶子数加
Leaf(T >rchild); //遍历右子树
return leaves;
//算法结束 #include
void main()
//测试程序
BinTree root;
CreatBinTree(&root);
int nodes=Node(root);
int leaves=Leaf(root);
printf( \\nnodes=%d leaves=%d nodes leaves);
以二叉链表为存储结构 分别写出求二叉树高度及宽度的算法 所谓宽度是指二叉树的各层上 具有结点数最多的那一层上的结点总数
解 要想求出二叉树的高度 可以采用前序遍历 设一个个记录高度的变量h 在访问结点时查询该结点是否有孩子 有则高度加 其中根结点比特殊 自身算一层 要求二叉树的宽度的话 则可根据树的高度设置一个数组 在访问结点时计算该结点下一层的孩子数并存入相应数组元素中 遍历左子树后向上返回一层计算右子树的宽度 并取出最大的一个数组元素作为树的宽度
#include
#include bintree h
#define M //假设二叉树最多的层数
int Height(BinTree T)//求树的深度
//求深度算法由阮允准更正 在此深表感谢
int lhigh rhigh high= ;
if(T!=NULL)
lhigh=Height(T >lchild);//左子树高度
rhigh=Height(T >rchild);//右子树高度
high=(lhigh>rhigh?lhigh:rhigh)+ ;//树的高度等于左子树 右子树之间的大者加上根结点
return high;
int Width(BinTree T)
int static n[M];//向量存放各层结点数
int static i= ;
int static max= ;//最大宽度
if(T)
if(i== ) //若是访问根结点
n[i]++; //第 层加
i++; //到第 层
if(T >lchild)//若有左孩子则该层加
n[i]++;
if(T >rchild)//若有右孩子则该层加
n[i]++;
else
//访问子树结点
i++; //下一层结点数
if(T >lchild)
n[i]++;
if(T >rchild)
n[i]++;
if(max
Width(T->lchild);//遍历左子树
i--; //往上退一层
Width(T->rchild);//遍历右子树
return max;
//算法结束 void main()
//测试程序
BinTree root;
CreatBinTree (&root);
printf("\\nHeight of BinTree:%d",Height(root));
printf("\\nWidth of BinTree:%d",Width(root));
6.25 以二叉链表为存储结构, 写一算法交换各结点的左右子树。Tw.WiNgWiT.
要交换各结点的左右子树,最方便的办法是用后序遍历算法,每访问一个结点时把两棵子树的指针进行交换,最后一次访问是交换根结点的子树。
#include
#include "bintree.h"
void ChangeBinTree(BinTree *T)
//交换子树
if(*T)
//这里以指针为参数使得交换在实参的结点上进行
//后序遍历
BinTree temp;
ChangeBinTree(&(*T)->lchild);
ChangeBinTree(&(*T)->rchild);
temp=(*T)->lchild;
(*T)->lchild=(*T)->rchild;
(*T)->rchild=temp;
void PrintNode(BinTree T)
//以前序序列打印结点数据
if(T)
printf("%c",T->data);
PrintNode(T->lchild);
相关参考