二叉树——链式存储结构

第一关 二叉树创建及遍历

任务描述

本关任务:实现二叉树的创建函数及二叉树的遍历函数。

相关知识

二叉树可用顺序方式存储,也可使用链式存储,本关使用二叉树的链式存储方式。结点数据结构定义为:

 
  1. struct node
  2. {
  3. DataType info ;
  4. struct node *lchild , *rchild ;
  5. };

二叉树的链式存储结构举例如下图所示:

创建二叉树时,可采用递归算法,其中一种方法是,将二叉树先扩充为扩二叉树,然后按先序遍历的结点顺序输入,如:

上图中,#结点为扩充的外部结点,输入该二叉树时输入结点顺序为: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);              // 后根遍历
}

这段程序实现了二叉树的创建和三种遍历方式(先根遍历、中根遍历和后根遍历)的功能。

具体说明如下:

  1. 定义了二叉树的数据结构 node,包括 info(存放结点数据)、lchild(指向左孩子的指针)和 rchild(指向右孩子的指针)。
  2. 定义了二叉树结构体指针类型 BiTree
  3. createBiTree 函数用于创建二叉树,通过递归方式实现。用户从键盘输入二叉树的结点数据,以先序方式构建二叉树,并返回根结点指针。
  4. visit 函数用于输出结点的数据。
  5. preOrder 函数用于先根遍历二叉树,先访问根结点,然后递归遍历左子树和右子树。
  6. inOrder 函数用于中根遍历二叉树,先递归遍历左子树,然后访问根结点,最后递归遍历右子树。
  7. postOrder 函数用于后根遍历二叉树,先递归遍历左子树,然后递归遍历右子树,最后访问根结点。
  8. 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);       // 输出二叉树中叶子结点的个数
}

这段程序的功能是创建一个二叉树,并计算该二叉树中叶子节点的个数。

具体功能说明如下:

  1. 定义了二叉树的数据结构 node,包括 info(存放结点数据)、lchild(指向左孩子的指针)和 rchild(指向右孩子的指针)。
  2. 定义了二叉树结构体指针类型 BiTree
  3. createBiTree 函数用于创建二叉树,通过递归方式实现。用户从键盘输入二叉树的结点数据,以先序方式构建二叉树,并返回根结点指针。
  4. visit 函数用于输出结点的数据。
  5. countLeaf 函数用于计算二叉树中叶子结点的个数。通过递归遍历二叉树,当遍历到叶子结点时,计数加一,然后递归统计左子树和右子树中的叶子结点个数,并将结果累加。
  6. 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);                 // 中序遍历
}

这段程序的功能如下:

  1. 定义了一个二叉树的数据结构,其中每个节点包含一个字符类型的数据和指向左右孩子的指针。
  2. 提供了函数createBiTree用于创建二叉树。它通过递归方式读取用户输入的字符,如果输入的字符是'#',表示空节点;否则,创建一个新节点并设置节点数据,然后递归创建左子树和右子树,并将它们链接到当前节点。
  3. 提供了函数changeLR用于实现二叉树的左右子树互换。它通过递归方式遍历二叉树的所有节点,对于每个节点,交换其左右子树的指针。
  4. 提供了函数visit用于输出节点的数据。
  5. 提供了函数inOrder用于中序遍历二叉树。它通过递归方式遍历二叉树的所有节点,先访问左子树,然后输出当前节点的数据,最后访问右子树。
  6. 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);   // 输出二叉树中满结点的个数
}

这段程序的功能如下:

  1. 定义了一个二叉树的数据结构,其中每个节点包含一个字符类型的数据和指向左右孩子的指针。
  2. 提供了函数 createBiTree 用于创建二叉树。它通过递归方式读取用户输入的字符,如果输入的字符是 '#',表示空节点;否则,创建一个新节点并设置节点数据,然后递归创建左子树和右子树,并将它们链接到当前节点。
  3. 提供了函数 visit 用于输出节点的数据。
  4. 提供了函数 countFullNode 用于计算二叉树中满结点(即同时具有左子树和右子树的节点)的个数。它通过递归方式遍历二叉树的所有节点,对于每个节点,如果其左子树和右子树都不为空,则将计数加一,并递归计算左子树和右子树中的满结点个数。
  5. main 函数中,首先调用 createBiTree 创建二叉树,并将根节点指针赋给变量 root。然后,调用 countFullNode 函数计算二叉树中满结点的个数,并将结果输出到标准输出流(屏幕)上。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值