第一关 二叉树创建及遍历
任务描述
本关任务:实现二叉树的创建函数及二叉树的遍历函数。
相关知识
二叉树可用顺序方式存储,也可使用链式存储,本关使用二叉树的链式存储方式。结点数据结构定义为:
struct node
{
DataType info ;
struct node *lchild , *rchild ;
};
二叉树的链式存储结构举例如下图所示:
创建二叉树时,可采用递归算法,其中一种方法是,将二叉树先扩充为扩二叉树,然后按先序遍历的结点顺序输入,如:
上图中,#
结点为扩充的外部结点,输入该二叉树时输入结点顺序为:AB#DF###CE#G###
#include <iostream>
using namespace std;
typedef char DataType;
// 二叉树数据结构
struct node
{
DataType info; // 存放结点数据
struct node* lchild; // 指向左孩子的指针
struct node* rchild; // 指向右孩子的指针
};
typedef struct node* BiTree; // 定义二叉树结构体指针类型
/* 创建二叉树
函数名:createBiTree
参数:无
返回值:二叉树根结点指针
*/
BiTree createBiTree(void)
{
// 请在此处填写代码,完成二叉树的创建,返回值是二叉树的根结点指针
/********** Begin **********/
DataType ch;
struct node* tree;
cin >> ch; // 读取输入的字符
if (ch == '#') // 如果输入的字符是 '#',表示空结点
return NULL;
else
{
// 分配内存空间创建新结点
tree = (struct node*)malloc(sizeof(struct node));
tree->info = ch; // 设置结点数据
tree->lchild = createBiTree(); // 递归创建左子树
tree->rchild = createBiTree(); // 递归创建右子树
return tree; // 返回根结点指针
}
/********** End *********/
}
void visit(BiTree T)
{
cout << T->info; // 输出结点T的数据
}
// 先根遍历二叉树
void preOrder(BiTree root)
{
/********** Begin **********/
if (root == NULL)
return;
visit(root); // 访问根结点
preOrder(root->lchild); // 递归先根遍历左子树
preOrder(root->rchild); // 递归先根遍历右子树
/********** End *********/
}
// 中根遍历二叉树
void inOrder(BiTree root)
{
if (root == NULL)
return;
inOrder(root->lchild); // 递归中根遍历左子树
visit(root); // 访问根结点
inOrder(root->rchild); // 递归中根遍历右子树
}
// 后根遍历二叉树
void postOrder(BiTree root)
{
/********** Begin **********/
if (root == NULL)
return;
postOrder(root->lchild); // 递归后根遍历左子树
postOrder(root->rchild); // 递归后根遍历右子树
visit(root); // 访问根结点
/********** End *********/
}
int main(void)
{
BiTree root = createBiTree(); // 创建二叉树,获取根结点指针
preOrder(root); // 先根遍历
cout << '\n';
inOrder(root); // 中根遍历
cout << '\n';
postOrder(root); // 后根遍历
}
这段程序实现了二叉树的创建和三种遍历方式(先根遍历、中根遍历和后根遍历)的功能。
具体说明如下:
- 定义了二叉树的数据结构
node
,包括info
(存放结点数据)、lchild
(指向左孩子的指针)和rchild
(指向右孩子的指针)。 - 定义了二叉树结构体指针类型
BiTree
。 createBiTree
函数用于创建二叉树,通过递归方式实现。用户从键盘输入二叉树的结点数据,以先序方式构建二叉树,并返回根结点指针。visit
函数用于输出结点的数据。preOrder
函数用于先根遍历二叉树,先访问根结点,然后递归遍历左子树和右子树。inOrder
函数用于中根遍历二叉树,先递归遍历左子树,然后访问根结点,最后递归遍历右子树。postOrder
函数用于后根遍历二叉树,先递归遍历左子树,然后递归遍历右子树,最后访问根结点。main
函数通过调用createBiTree
创建二叉树,并依次调用先根遍历、中根遍历和后根遍历函数,输出遍历结果。
第二关 计算二叉树中叶子的个数
任务描述
本关任务:在完成第一关的基础上,编写一个函数,能计算一棵二叉树中树叶的个数并输出。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:AB#DF###CE#G###
预期输出:2
#include <iostream>
using namespace std;
typedef char DataType;
// 二叉树数据结构
struct node
{
DataType info; // 存放结点数据
struct node* lchild; // 指向左孩子的指针
struct node* rchild; // 指向右孩子的指针
};
typedef struct node* BiTree; // 定义二叉树结构体指针类型
/* 创建二叉树
函数名:createBiTree
参数:无
返回值:二叉树根结点指针
*/
BiTree createBiTree(void)
{
char ch;
BiTree root;
cin >> ch; // 读取输入的字符
if (ch == '#') // 如果输入的字符是 '#',表示空结点
root = NULL;
else
{
// 分配内存空间创建新结点
root = new struct node;
root->info = ch; // 设置结点数据
root->lchild = createBiTree(); // 递归创建左子树
root->rchild = createBiTree(); // 递归创建右子树
}
return root;
}
void visit(BiTree T)
{
cout << T->info; // 输出结点T的数据
}
int countLeaf(BiTree root)
{
// 请在此处填写代码,计算二叉树中叶子结点的个数
/********** Begin **********/
int count = 0;
if (root == NULL)
return count;
// 判断是否为叶子结点,若是则计数加一
if (root->lchild == NULL && root->rchild == NULL)
count++;
// 递归统计左子树和右子树中叶子结点的个数
count += countLeaf(root->lchild);
count += countLeaf(root->rchild);
return count;
/********** End **********/
}
int main(void)
{
BiTree root = createBiTree(); // 创建二叉树,获取根结点指针
cout << countLeaf(root); // 输出二叉树中叶子结点的个数
}
这段程序的功能是创建一个二叉树,并计算该二叉树中叶子节点的个数。
具体功能说明如下:
- 定义了二叉树的数据结构
node
,包括info
(存放结点数据)、lchild
(指向左孩子的指针)和rchild
(指向右孩子的指针)。 - 定义了二叉树结构体指针类型
BiTree
。 createBiTree
函数用于创建二叉树,通过递归方式实现。用户从键盘输入二叉树的结点数据,以先序方式构建二叉树,并返回根结点指针。visit
函数用于输出结点的数据。countLeaf
函数用于计算二叉树中叶子结点的个数。通过递归遍历二叉树,当遍历到叶子结点时,计数加一,然后递归统计左子树和右子树中的叶子结点个数,并将结果累加。main
函数通过调用createBiTree
创建二叉树,并调用countLeaf
计算叶子结点的个数,并将结果输出。
第三关 实现二叉树左右子树互换
任务描述
本关任务:编写一个把二叉树左右子树交换的函数。
以下图一所示的二叉树为例,左右子树交换后如图二所示。
测试输入:ABC####
预期输出(中序遍历):ABC
#include <iostream>
using namespace std;
typedef char DataType;
// 二叉树数据结构
struct node
{
DataType info; // 存放结点数据
struct node* lchild; // 指向左孩子的指针
struct node* rchild; // 指向右孩子的指针
};
typedef struct node* BiTree; // 定义二叉树结构体指针类型
/* 创建二叉树
函数名:createBiTree
参数:无
返回值:二叉树根结点指针
*/
BiTree createBiTree(void)
{
char ch;
BiTree root;
cin >> ch; // 读取输入的字符
if (ch == '#') // 如果输入的字符是 '#',表示空结点
root = NULL;
else
{
// 分配内存空间创建新结点
root = new struct node;
root->info = ch; // 设置结点数据
root->lchild = createBiTree(); // 递归创建左子树
root->rchild = createBiTree(); // 递归创建右子树
}
return root;
}
void changeLR(BiTree root)
{
// 请在此处填写代码,完成二叉树左右子树互换
/********** Begin **********/
if (root == NULL)
return;
else
{
BiTree tree = root->lchild;
root->lchild = root->rchild;
root->rchild = tree;
changeLR(root->lchild);
changeLR(root->rchild);
}
/********** End **********/
}
void visit(BiTree T) // 输出结点T的数据
{
cout << T->info;
}
void inOrder(BiTree root)
{
if (root == NULL)
return;
inOrder(root->lchild);
visit(root);
inOrder(root->rchild);
}
int main(void)
{
BiTree root = createBiTree(); // 创建二叉树,获取根结点指针
changeLR(root); // 左右子树互换
inOrder(root); // 中序遍历
}
这段程序的功能如下:
- 定义了一个二叉树的数据结构,其中每个节点包含一个字符类型的数据和指向左右孩子的指针。
- 提供了函数
createBiTree
用于创建二叉树。它通过递归方式读取用户输入的字符,如果输入的字符是'#',表示空节点;否则,创建一个新节点并设置节点数据,然后递归创建左子树和右子树,并将它们链接到当前节点。 - 提供了函数
changeLR
用于实现二叉树的左右子树互换。它通过递归方式遍历二叉树的所有节点,对于每个节点,交换其左右子树的指针。 - 提供了函数
visit
用于输出节点的数据。 - 提供了函数
inOrder
用于中序遍历二叉树。它通过递归方式遍历二叉树的所有节点,先访问左子树,然后输出当前节点的数据,最后访问右子树。 - 在
main
函数中,首先调用createBiTree
创建二叉树,并将根节点指针赋值给root
变量。然后调用changeLR
函数对二叉树进行左右子树互换。最后调用inOrder
函数进行中序遍历,输出互换后的二叉树节点数据。
第四关 计算二叉树中有两个孩子的结点个数
任务描述
本关任务:编写一个能计算二叉树中有两个孩子的满结点个数。
测试输入:ABC####
预期输出:0
#include <iostream>
using namespace std;
typedef char DataType;
// 二叉树数据结构
struct node
{
DataType info; // 存放结点数据
struct node* lchild, * rchild; // 指向左右孩子的指针
};
typedef struct node* BiTree; // 定义二叉树结构体指针类型
/* 创建二叉树
函数名:createBiTree
参数:无
返回值:二叉树根结点指针
*/
BiTree createBiTree(void)
{
char ch;
BiTree root;
cin >> ch; // 读取输入的字符
if (ch == '#') // 如果输入的字符是 '#',表示空结点
root = NULL;
else
{
// 分配内存空间创建新结点
root = new struct node;
root->info = ch; // 设置结点数据
root->lchild = createBiTree(); // 递归创建左子树
root->rchild = createBiTree(); // 递归创建右子树
}
return root;
}
void visit(BiTree T)
{
cout << T->info;
}
int countFullNode(BiTree root)
{
// 请在此处填写代码,计算二叉树中满结点的个数
/********** Begin **********/
if (root == NULL)
return 0;
int count = 0;
if (root->lchild != NULL && root->rchild != NULL)
count = 1;
count += countFullNode(root->lchild);
count += countFullNode(root->rchild);
return count;
/*********** End **********/
}
int main(void)
{
BiTree root = createBiTree(); // 创建二叉树,获取根结点指针
cout << countFullNode(root); // 输出二叉树中满结点的个数
}
这段程序的功能如下:
- 定义了一个二叉树的数据结构,其中每个节点包含一个字符类型的数据和指向左右孩子的指针。
- 提供了函数
createBiTree
用于创建二叉树。它通过递归方式读取用户输入的字符,如果输入的字符是 '#',表示空节点;否则,创建一个新节点并设置节点数据,然后递归创建左子树和右子树,并将它们链接到当前节点。 - 提供了函数
visit
用于输出节点的数据。 - 提供了函数
countFullNode
用于计算二叉树中满结点(即同时具有左子树和右子树的节点)的个数。它通过递归方式遍历二叉树的所有节点,对于每个节点,如果其左子树和右子树都不为空,则将计数加一,并递归计算左子树和右子树中的满结点个数。 - 在
main
函数中,首先调用createBiTree
创建二叉树,并将根节点指针赋给变量root
。然后,调用countFullNode
函数计算二叉树中满结点的个数,并将结果输出到标准输出流(屏幕)上。