【数据结构 06】二叉树

本文介绍了二叉树的基本概念,如满二叉树、完全二叉树的特性,以及如何使用C++实现二叉树的创建、遍历和操作,包括节点数计算、叶子节点数、深度和子树数量等。
摘要由CSDN通过智能技术生成

一、原理

二叉树算法核心思维:递归

满二叉树:二叉树的层数为K,节点数为2^K - 1

完全二叉树:二叉树的层数为K,前K-1层是满的,第K层是连续的

满二叉树是完全二叉树的子集。

任意二叉树:若叶子节点的个数是n_o,设度为2(有2个子节点)的节点个数是n_2,则n_0 = n_2 + 1

二叉树的第i层上最多有2^{i-1}个节点,第n个节点的满二叉树深度h = \lg (n+1)

二叉树可以顺序存储或链式存储。

二、BinaryTree.h

#define _CRT_SECURE_NO_WARNINGS 1

#pragma
#include <iostream>
#include <string>
#include <cassert>
using namespace std;

typedef char DataType;

struct BinaryTreeNode
{
	DataType data;
	BinaryTreeNode* left;
	BinaryTreeNode* right;

	BinaryTreeNode(DataType x)
		: data(x), left(nullptr), right(nullptr)
	{}
};

class BinaryTree
{
	typedef BinaryTreeNode Node;
public:
	// 构建,指定构造数据序列
	void Create(const DataType* datas, int& i)
	{
		_root = _Create(datas, i);
	}

	// 先序遍历(根、左、右)
	void PreOrder()
	{
		_PreOrder(_root);
		cout << ",先序遍历结束" << endl;
	}

	// 中序遍历
	void InOrder()
	{
		_InOrder(_root);
		cout << ",中序遍历结束" << endl;
	}

	// 后序遍历
	void PastOrder()
	{
		_PastOrder(_root);
		cout << ",后序遍历结束" << endl;
	}

	// 总节点数
	int Size()
	{
		int num = 0;
		_Size(_root, num);
		return num;
	}

	// 叶子节点数
	int LeafSize()
	{
		int leafNum = 0;
		_LeafSize(_root, leafNum);
		return leafNum;
	}

	// 深度(层数)
	int Depth()
	{
		return _Depth(_root);
	}

	// 子树数量
	int TreeSize()
	{
		return _TreeSize(_root);
	}

	// 销毁
	void Destroy()
	{
		_Destroy(_root);
		_root = nullptr;
		cout << "二叉树销毁成功" << endl;
	}

private:
	Node* _Create(const DataType* datas, int& i)
	{
		if (datas[i] == '#')
			return nullptr;

		Node* root = new Node(datas[i]);
		root->left = _Create(datas, ++i);
		root->right = _Create(datas, ++i);
		return root;
	}

	void _PreOrder(Node* root)
	{
		if (root == nullptr)
		{
			cout << "# ";
			return;
		}

		cout << root->data << ' ';
		_PreOrder(root->left);
		_PreOrder(root->right);
	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			cout << "# ";
			return;
		}

		_InOrder(root->left);
		cout << root->data << ' ';
		_InOrder(root->right);
	}

	void _PastOrder(Node* root)
	{
		if (root == nullptr)
		{
			cout << "# ";
			return;
		}

		_PastOrder(root->left);
		_PastOrder(root->right);
		cout << root->data << ' ';
	}

	void _Size(Node* root, int& num)
	{
		if (root == nullptr)
			return;

		++num;
		_Size(root->left, num);
		_Size(root->right, num);
	}

	void _LeafSize(Node* root, int& leafNum)
	{
		if (root == nullptr)
			return;

		if (root->left == nullptr && root->right == nullptr)
			leafNum++;
		_LeafSize(root->left, leafNum);
		_LeafSize(root->right, leafNum);
	}

	int _Depth(Node* root)
	{
		if (root == nullptr)
			return 0;

		int leftDepth = _Depth(root->left);
		int rightDepth = _Depth(root->right);

		return (leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1);
	}

	int _TreeSize(Node* root)
	{
		if (root == nullptr)
			return 0;

		return (root->left == nullptr && root->right == nullptr) ? 0 :
			_TreeSize(root->left) + _TreeSize(root->right) + 1;
	}

	void _Destroy(Node* root)
	{
		if (root == nullptr)
			return;
		
		_Destroy(root->left);
		_Destroy(root->right);
		cout << root->data << "销毁,";
		delete root;
	}

private:
	Node* _root;
};

三、test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "BinaryTree.h"

int main()
{
	cout << "--Test1---" << endl << "数据序列: 123###45##6##" << endl;
	BinaryTree bt;

	// 构建二叉树
	int i = 0;
	bt.Create("123###45##6##", i);
	bt.PreOrder();
	bt.InOrder();
	bt.PastOrder();

	// 计算二叉树节点总数
	cout << "二叉树节点总数为:" << bt.Size() << endl; // 6

	// 计算二叉树叶子结点数
	cout << "二叉树叶子结点数为:" << bt.LeafSize() << endl; // 3

	// 计算二叉树深度
	cout << "二叉树深度:" << bt.Depth() << endl; // 3

	// 计算二叉树子树数量
	cout << "二叉树子树数量:" << bt.TreeSize() << endl; // 3

	// 销毁二叉树
	bt.Destroy(); // 3销毁,2销毁,5销毁,6销毁,4销毁,1销毁,二叉树销毁成功

	// 计算二叉树节点总数
	cout << "二叉树节点总数为:" << bt.Size() << endl;

	return 0;
}

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllinTome

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值