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次)
}