C++实现一个简单的二叉树

C++实现一个简单的二叉树

/**---------------------------------------
* 文件名称: CBinaryTree.h
* 功能描述: 二叉树实现
* 创建标识: 肖澳笛 2022/2/9
*
* 修改标识:
* 修改描述:
------------------------------------------**/
#ifndef CBIANARYTREE_BINARYTREE_H
#define CBIANARYTREE_BINARYTREE_H

#include <string>

namespace Algo05
{
	typedef struct BINARYNODE
	{
		char _ch;						  //存储数据
		struct BINARYNODE*	 _pLeftNode;  //左孩子结点
		struct BINARYNODE*	_pRightNode;  //右孩子结点
	}BinaryNode;

	typedef struct BITREESTACKNODE
	{
		BinaryNode *		_pRoot;
		bool				_bFlag;
	}BiTreeStackNode;


	class CBinaryTree
	{
	private:
		BinaryNode *		_pRoot;   //根节点
	public:
		CBinaryTree();

		~CBinaryTree();

		/**
		*  @brief    创建二叉树
		*
		*  @return   void
		*/
		void createBinaryTree();

		/**
		*  @brief    创建二叉树
		*
		*  @param    char * nodeSeq
		*  @param    size_t num
		*  @return   void
		*/
		void createBinaryTree(char* nodeSeq, size_t num);

		/**
		*  @brief    先序遍历递归实现
		*
		*  @return   void
		*/
		void recursion();

		/**
		*  @brief    计算叶子结点数目
		*
		*  @return   void
		*/
		void calculateLeafNum();

		/**
		*  @brief    计算二叉树的高度
		*
		*  @return   void
		*/
		void calculateTreeHeight();

		/**
		*  @brief    先序遍历非递归实现,借助STL中的stack实现
		*
		*  @return   void
		*/
		void nonRecursion();

		/**
		*  @brief    序列化
		*
		*  @return   std::string
		*/
		std::string serializeTree();

		/**
		*  @brief    反序列化
		*
		*  @param    const std::string & treeSeq
		*  @return   void
		*/
		void deserializeTree(const std::string &treeSeq);

		// 重载赋值运算符,实现拷贝
		CBinaryTree& operator=(const CBinaryTree &tree);

	private:
		static void _freeBinaryTree(BinaryNode* currentRoot);

		static BinaryNode* _createBinaryTree(const char* nodeSeq, size_t num, int &pos);

		static void _recursion(BinaryNode* currentRoot);

		static void _calculateLeafNum(BinaryNode* currentRoot, int& num);

		static void _calculateTreeHeight(BinaryNode* currentRoot, int& height);

		static void _copyBinaryTree(BinaryNode* currentRoot, BinaryNode** copyRoot);

		static BinaryNode* _copyBinaryTree(BinaryNode* currentRoot);

		static std::string _serializeTree(BinaryNode* currentRoot);

		static BinaryNode* _deserializeTree(const std::string &treeSeq, int &pos);

	};


}

#endif
#include "CBinaryTree.h"
#include <iostream>
#include <stack>

using namespace Algo05;

Algo05::CBinaryTree::CBinaryTree()
{
	_pRoot = nullptr;
}

Algo05::CBinaryTree::~CBinaryTree()
{
	std::cout << "\n-------------------" << std::endl;
	std::cout << "free BinaryTree: ";
	_freeBinaryTree(_pRoot); //递归实现释放空间
}

void Algo05::CBinaryTree::createBinaryTree()
{
	// 创建结点
	// 这里必须使用new, 否则构造完成后各node会自动销毁!
	// 使用new之后,虽不会被自动销毁,但是必须手动在析构函数中释放内存!

	auto *node1 = new BinaryNode{ 'A', nullptr, nullptr };
	auto *node2 = new BinaryNode{ 'B', nullptr, nullptr };
	auto *node3 = new BinaryNode{ 'C', nullptr, nullptr };
	auto *node4 = new BinaryNode{ 'D', nullptr, nullptr };
	auto *node5 = new BinaryNode{ 'E', nullptr, nullptr };
	auto *node6 = new BinaryNode{ 'F', nullptr, nullptr };
	auto *node7 = new BinaryNode{ 'G', nullptr, nullptr };
	auto *node8 = new BinaryNode{ 'H', nullptr, nullptr };

	// 建立结点关系
	node1->_pLeftNode = node2;
	node1->_pRightNode = node6;
	node2->_pRightNode = node3;
	node3->_pLeftNode = node4;
	node3->_pRightNode = node5;
	node6->_pRightNode = node7;
	node7->_pLeftNode = node8;

	_pRoot = node1;
}

void Algo05::CBinaryTree::createBinaryTree(char * nodeSeq, size_t num)
{
	if (nodeSeq == nullptr) {
		return;
	}

	if (_pRoot != nullptr) {
		_freeBinaryTree(_pRoot);
	}

	int pos = 0;
	_pRoot = _createBinaryTree(nodeSeq, num, pos);

}

void Algo05::CBinaryTree::recursion()
{
	if (_pRoot == nullptr) {
		return;
	}
	_recursion(_pRoot);

}

void Algo05::CBinaryTree::calculateLeafNum()
{
	if (_pRoot == nullptr) {
		return;
	}
	int num = 0;
	_calculateLeafNum(_pRoot, num);
	std::cout << "叶子结点的数目:" << num << std::endl;

}

void Algo05::CBinaryTree::calculateTreeHeight()
{
	if (_pRoot == nullptr) {
		return;
	}
	int height = 0;
	_calculateTreeHeight(_pRoot, height);
	std::cout << "树的高度:" << height << std::endl;
}

void Algo05::CBinaryTree::nonRecursion()
{
	if (_pRoot == nullptr) {
		return;
	}

	std::stack<BiTreeStackNode> stk;
	BiTreeStackNode biTreeStackNode{ _pRoot, false };
	stk.push(biTreeStackNode);
	while (!stk.empty()) {
		BiTreeStackNode& node = stk.top();
		// 必须重新复制一个与node一样的结点,否则node一直指向stack栈顶,出现结果异常!
		BiTreeStackNode rootNode{ node._pRoot, node._bFlag };
		stk.pop();
		if (rootNode._pRoot == nullptr) {
			continue;
		}
		if (rootNode._bFlag) {
			std::cout << rootNode._pRoot->_ch << " ";
			continue;
		}
		rootNode._bFlag = true;

		// 通过控制入栈的顺序,可以分别实现前序、中序、后序遍历!

		// 当前结点的右结点入栈
		BiTreeStackNode rnode{ rootNode._pRoot->_pLeftNode, false };
		stk.push(rnode);
		// 当前结点的左结点入栈
		BiTreeStackNode lnode{ rootNode._pRoot->_pRightNode, false };
		stk.push(lnode);
		// 当前结点入栈
		stk.push(rootNode);
	}

}

std::string Algo05::CBinaryTree::serializeTree()
{
	return _serializeTree(_pRoot);
}

void Algo05::CBinaryTree::deserializeTree(const std::string & treeSeq)
{
	if (treeSeq.empty()) {
		return;
	}
	if (_pRoot != nullptr) {
		_freeBinaryTree(_pRoot);
	}
	int pos = 0;
	_pRoot = _deserializeTree(treeSeq, pos);

}

CBinaryTree & Algo05::CBinaryTree::operator=(const CBinaryTree & tree)
{
	// TODO: 在此处插入 return 语句
	if (tree._pRoot == nullptr) {
		return *this;
	}
	// 检查是否自我赋值!
	if (this == &tree) {
		return *this;
	}
	//    BinaryNode *root_;
	//    _copyBinaryTree(tree.root, &root_);
	this->_pRoot = _copyBinaryTree(tree._pRoot);
	return *this;
}

void Algo05::CBinaryTree::_freeBinaryTree(BinaryNode * currentRoot)
{
	// 后序遍历销毁各结点
	if (currentRoot == nullptr) {
		return;
	}
	// 释放左子树
	_freeBinaryTree(currentRoot->_pLeftNode);
	// 释放右子树
	_freeBinaryTree(currentRoot->_pRightNode);
	std::cout << currentRoot->_ch << " ";
	// 释放当前结点
	delete currentRoot;
}

BinaryNode * Algo05::CBinaryTree::_createBinaryTree(const char * nodeSeq, size_t num, int & pos)
{
	if (nodeSeq == nullptr) {
		return nullptr;
	}

	if (pos >= num) {
		return nullptr;
	}

	if (nodeSeq[pos] == '#') {
		pos++;
		return nullptr;
	}

	auto pNode = new BinaryNode{ nodeSeq[pos], nullptr, nullptr };
	pos++;
	pNode->_pLeftNode = _createBinaryTree(nodeSeq, num, pos);
	pNode->_pRightNode = _createBinaryTree(nodeSeq, num, pos);
	return pNode;

}

void Algo05::CBinaryTree::_recursion(BinaryNode * currentRoot)
{
	if (currentRoot == nullptr) {
		return;
	}

	// 访问根结点
	std::cout << currentRoot->_ch << " ";

	// 遍历左子树
	_recursion(currentRoot->_pLeftNode);

	// 遍历右子树
	_recursion(currentRoot->_pRightNode);

}

void Algo05::CBinaryTree::_calculateLeafNum(BinaryNode * currentRoot, int & num)
{
	if (currentRoot == nullptr)
	{
		return;
	}

	if (currentRoot->_pLeftNode == nullptr && currentRoot->_pRightNode == nullptr)
	{
		num++;
	}

	/// 左子树叶子结点数目
	_calculateLeafNum(currentRoot->_pLeftNode, num);

	///右子树叶子结点数目
	_calculateLeafNum(currentRoot->_pRightNode, num);
}

void Algo05::CBinaryTree::_calculateTreeHeight(BinaryNode * currentRoot, int & height)
{
	if (currentRoot == nullptr) {
		return;
	}

	int lh = 0, rh = 0;
	_calculateTreeHeight(currentRoot->_pLeftNode, lh);
	_calculateTreeHeight(currentRoot->_pRightNode, rh);
	height = 1 + ((lh > rh) ? lh : rh);

}

void Algo05::CBinaryTree::_copyBinaryTree(BinaryNode * currentRoot, BinaryNode ** copyRoot)
{
	if (currentRoot == nullptr) {
		return;
	}
	*copyRoot = new BinaryNode{ currentRoot->_ch, nullptr, nullptr };
	_copyBinaryTree(currentRoot->_pLeftNode, &((*copyRoot)->_pLeftNode));
	_copyBinaryTree(currentRoot->_pRightNode, &((*copyRoot)->_pRightNode));

}

BinaryNode * Algo05::CBinaryTree::_copyBinaryTree(BinaryNode * currentRoot)
{
	if (currentRoot == nullptr) {
		return nullptr;
	}
	// 拷贝左子树
	BinaryNode *lchild = _copyBinaryTree(currentRoot->_pLeftNode);

	// 拷贝右子树
	BinaryNode *rchild = _copyBinaryTree(currentRoot->_pRightNode);

	// 创建结点
	auto *newNode = new BinaryNode{ currentRoot->_ch, lchild, rchild };
	return newNode;

}

std::string Algo05::CBinaryTree::_serializeTree(BinaryNode * currentRoot)
{
	return std::string();
}

BinaryNode * Algo05::CBinaryTree::_deserializeTree(const std::string & treeSeq, int & pos)
{
	if (treeSeq.empty()) {
		return nullptr;
	}
	if (pos >= treeSeq.size()) {
		return nullptr;
	}
	char ch = treeSeq.at(pos);
	if (ch == '#') {
		pos++;
		return nullptr;
	}
	auto *node = new BinaryNode{ ch, nullptr, nullptr };
	pos++;
	node->_pLeftNode = _deserializeTree(treeSeq, pos);
	node->_pRightNode = _deserializeTree(treeSeq, pos);
	return node;

}

#include <iostream>
#include "CBinaryTree.h"

using namespace std;
using namespace Algo05;

void test_06(void);

int main() 
{
	test_06();
	system("pause");
	return 0;
}

void test_06(void)
{
	CBinaryTree tree;
	tree.createBinaryTree();

	// 递归前序遍历
	std::cout << "递归前序遍历:" << std::endl;
	tree.recursion();
	std::cout << "\n****************************" << std::endl;

	// 计算叶子结点数目
	tree.calculateLeafNum();
	std::cout << "****************************" << std::endl;

	// 计算二叉树的高度
	tree.calculateTreeHeight();
	std::cout << "****************************" << std::endl;

	// 非递归前序遍历
	std::cout << "非递归前序遍历:" << std::endl;
	tree.nonRecursion();
	std::cout << "\n****************************" << std::endl;
	CBinaryTree copyTree;

	// 深拷贝二叉树
	std::cout << "拷贝二叉树..." << std::endl;
	copyTree = tree;
	std::cout << "拷贝二叉树的前序遍历:" << std::endl;
	copyTree.recursion();
	std::cout << "\n****************************" << std::endl;

	// #号法创建二叉树
	char nodeSeq[] = { 'A', 'B', '#', 'C', 'D', '#', '#', 'E','#', '#', 'F', '#', 'G', 'H', '#', '#', '#' };
	int num = 17;
	CBinaryTree seqTree;
	std::cout << "#号法创建二叉树..." << std::endl;
	seqTree.createBinaryTree(nodeSeq, num);
	std::cout << "#号法创建二叉树前序遍历:" << std::endl;
	seqTree.recursion();
	std::cout << "\n****************************" << std::endl;

	// 二叉树的反序列化与序列化
	std::string nodeSeqStr = "AB#CD##E##F#GH###";
	CBinaryTree seqTree2;
	std::cout << "二叉树反序列化-" << nodeSeqStr << "..." << std::endl;
	seqTree2.deserializeTree(nodeSeqStr);
	std::cout << "反序列化二叉树前序遍历:" << std::endl;
	seqTree2.recursion();
	std::cout << "\n二叉树序列化:" << std::endl;
	std::string nodeSeqStr2 = seqTree2.serializeTree();
	std::cout << nodeSeqStr2 << std::endl;

	// 自动调用析构函数释放内存(4次)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值