实验目的:
1.掌握二叉树的定义;
2.掌握二叉树的基本操作,如二叉树的建立、遍历、结点个数统计、树的深度计算等。
实验内容:
用递归的方法实现以下算法:
1.以二叉链表表示二叉树,建立一棵二叉树;
2.输出二叉树的中序遍历结果;
3.输出二叉树的前序遍历结果;
4.输出二叉树的后序遍历结果;
5.计算二叉树的深度;
6.统计二叉树的结点个数;
7.统计二叉树的叶结点个数;
8.统计二叉树的度为1的结点个数;
9.输出二叉树中从每个叶子结点到根结点的路径。
选做内容
1.交换二叉树每个结点的左孩子和右孩子;
2.设计二叉树的双序遍历(DblOrderTraverse)算法(双序遍历是指对于二叉树的每一个结点来说,先访问这个结点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树)。
实验提示:
7.统计二叉树的叶结点个数
int LeafNodeCount(BiTree T ){
如果是空树,则叶子个数为0;
如果是叶子结点,则叶子结点个数为1(如何表示叶子结点???)
否则叶结点个数为左子树的叶结点个数+右子树的叶结点个数
}
实验要求:
(1) 程序要具有一定的健壮性,即当输入数据非法时,程序也能适当地做出反应。
(2) 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。
代码:
//--------------二叉树--------------二叉树--------------二叉树--------------
#include<stdio.h>
#include<stdlib.h>
#define MAX 20
typedef struct BTree {
char data;
struct BTree* left, * right;
}BTree, * ZBTree;
//创建二叉树
void CreateBTree(ZBTree& T) {
char e;
scanf("%c", &e);
if (e == '#')T = NULL;//给左或右赋值为NULL
else {
T = (ZBTree)malloc(sizeof(BTree));
T->data = e;
CreateBTree(T->left);//根变成左子
CreateBTree(T->right);//根变成右子
}
}
// 前序遍历
void PreOrderTree(ZBTree T) {
if (T) {
printf("%c", T->data);
PreOrderTree(T->left);
PreOrderTree(T->right);
}
}
//中序遍历
void InOrderTree(ZBTree T) {
if (T) {
InOrderTree(T->left);
printf("%c", T->data);
InOrderTree(T->right);
}
}
//后序遍历
void PostOrderTree(ZBTree T) {
if (T) {
PostOrderTree(T->left);
PostOrderTree(T->right);
printf("%c", T->data);
}
}
//二叉树深度
int DepthTree(ZBTree T) {
if (T == NULL) {
return 0;
}
else {
int Ldepth = DepthTree(T->left);//递归遍历根
int Rdepth = DepthTree(T->right);//递归遍历根
if (Ldepth > Rdepth)return Ldepth + 1;//返回最大的深度
else return Rdepth + 1;
}
}
//二叉树结点个数
int NodeTree(ZBTree T) {
if (T == NULL) return 0;
else return NodeTree(T->left) + NodeTree(T->right) + 1;//遍历根积累
} //相加结点数
//二叉树叶节点个数
int LeafTree(ZBTree T) {
if (T == NULL)return 0;
else if (T->left == NULL && T->right == NULL)return 1;//如果是叶节点才会+1
else return LeafTree(T->left) + LeafTree(T->right);//递归遍历根结点将
} //积累的数相加
//度为1的结点个数
int OneTree(ZBTree T) {
if (T == NULL)return 0;
else if ((T->left == NULL && T->right != NULL) || (T->left != NULL && T->right == NULL))
return OneTree(T->left) + OneTree(T->right) + 1;//度为1则+1
else return OneTree(T->left) + OneTree(T->right);//有孩子的话就返回子
}
//输出二叉树中从每个叶子结点到根结点的路径
void PathTree(ZBTree T, char path[], int& location)
{
if (T == NULL)return;
if (T->left == NULL && T->right == NULL)//如果是叶子则存到数组
{
path[location] = T->data;
printf("%c叶子节点到根节点的路径为: ", T->data);//输出叶子结点作为题目
for (int i = location; i >= 0; i--)
printf("%c ", path[i]);
printf("\n");
}
else
{
path[location++] = T->data;//从根开始传入数组
PathTree(T->left, path, location);//遍历根
PathTree(T->right, path, location);//遍历根
location--;//因为上面有location++,所以这个时候location的位置是没有值的,所以要location--
}
}
//交换二叉树每个结点的左孩子和右孩子(选做)
void ChangeTree(ZBTree& T) {
if (T == NULL)return;
ZBTree temp;
temp = T->left;
T->left = T->right;
T->right = temp;
ChangeTree(T->left);//递归遍历换根结点
ChangeTree(T->right);//递归遍历换根结点
}
//二叉树的双序遍历(DblOrderTraverse)算法
void BOrderTree(ZBTree T)
{//二叉树的双序遍历
if (T == NULL)return;
printf("%c", T->data);
BOrderTree(T->left);
printf("%c", T->data);//访问两遍
BOrderTree(T->right);
}
int main() {
ZBTree T;
char path[MAX];
int location = 0;
printf("先序遍历创建二叉树(ABC##D##EF###):\n");
CreateBTree(T);//建立
printf("建立二叉树成功!\n");
printf("前序遍历:");
PreOrderTree(T);//前序遍历
printf("\n");
printf("中序遍历:");
InOrderTree(T);//中序遍历
printf("\n");
printf("后序遍历:");
PostOrderTree(T);//后序遍历
printf("\n");
printf("深度为:%d\n", DepthTree(T));//深度
printf("结点个数为:%d\n", NodeTree(T)); //结点个数
printf("叶子结点个数为:%d\n", LeafTree(T));//叶子结点个数
printf("度为1的结点个数为:%d\n", OneTree(T));//度为1的结点数
ChangeTree(T);//左右子结点互换
printf("左右交换完成!\n");
PathTree(T,path,location);//输出各叶子到根的路径
printf("双序遍历:");
BOrderTree(T);//双序遍历
return 0;
}
运行结果+图