数据结构之二叉树

本文详细介绍了如何在C++中定义二叉树结构,包括其节点类和二叉树类,以及提供了层序、先序、中序和后序遍历的方法。同时,还展示了如何将二叉树序列化和反序列化的过程。
摘要由CSDN通过智能技术生成

二叉树的定义及其相关算法

//header.h
#pragma once
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <string>

template<typename T>
struct TreeNode
{
	T Value;
	TreeNode* leftChild;
	TreeNode* rightChild;
	TreeNode(const T& value)
		: Value{ value }, leftChild{ nullptr }, rightChild{ nullptr }
	{
		//std::cout << "Creating TreeNode: " << Value << '\n';
	}

	~TreeNode()
	{
		//std::cout << "Destroying TreeNode: " << Value << '\n';
	}
};

template<typename T>
class BinaryTree
{
private:
	TreeNode<T>* root;

public:
	BinaryTree() : root{ nullptr } {}
	BinaryTree& insert(const T& value);
	//层序遍历
	const BinaryTree& hierarchicalTraversal() const;
	//先序遍历序列
	const BinaryTree& preOrderTraversal(std::vector<T>& preOrder) const;
	//中序遍历序列
	const BinaryTree& inOrderTraversal(std::vector<T>& inOrder) const;
	//后序遍历序列
	const BinaryTree& postOrderTraversal(std::vector<T>& postOrder) const;
	//从先序和中序遍历序列构建二叉树
	BinaryTree& buildTreeFromPreAndInOrder(std::vector<T>& preOrder, std::vector<T>& inOrder);
	//从中序和后续遍历序列构建二叉树
	BinaryTree& buildTreeFromInAndPostOrder(std::vector<T>& inOrder, std::vector<T>& postOrder);
	//从先序遍历序列序列化二叉树
	std::string serializeFromPreOrder() const;
	//从中序遍历序列序列化二叉树
	std::string serializeFromInOrder() const;
	//从后序遍历序列序列化二叉树
	std::string serializeFromPostOrder() const;
	//从先序遍历序列反序列化二叉树
	BinaryTree& deserializeFromPreOrder(std::string data);
	//从中序遍历序列反序列化二叉树
	BinaryTree& deserializeFromInOrder(std::string data);
	//从后序遍历序列反序列化二叉树
	BinaryTree& deserializeFromPostOrder(std::string data);
	~BinaryTree();
};

//二叉平凡树插入算法
template<typename T>
BinaryTree<T>& BinaryTree<T>::insert(const T& value)
{
	TreeNode<T>* newNode = new TreeNode<T>{ value };

	if (this->root == nullptr)
	{
		this->root = newNode;
		return *this;
	}

	TreeNode<T>* temp = nullptr;
	bool flag = true;
	std::queue<TreeNode<T>*> que{};
	que.push(this->root);

	while (flag)
	{
		int n = que.size();
		for (int i = 0; i < n; ++i)
		{
			temp = que.front();
			que.pop();

			if (temp->leftChild == nullptr)
			{
				temp->leftChild = newNode;
				flag = false;
				break;
			}
			else
			{
				que.push(temp->leftChild);
			}

			if (temp->rightChild == nullptr)
			{
				temp->rightChild = newNode;
				flag = false;
				break;
			}
			else
			{
				que.push(temp->rightChild);
			}
		}
	}
	return *this;
}

template<typename T>
const BinaryTree<T>& BinaryTree<T>::hierarchicalTraversal() const
{
	if (this->root == nullptr)
	{
		std::cout << "This binary tree is empty!!! Can not hierarchicalTraversal!!!\n";
		return *this;
	}

	std::cout << "HierarchicalTraversal as belows:\n";
	TreeNode<T>* temp = nullptr;
	std::queue<TreeNode<T>*> helper;
	helper.push(this->root);

	while (!helper.empty())
	{
		int n = helper.size();
		//for循环可以清晰地看出是层上的遍历
		for (int i = 0; i < n; ++i)
		{
			temp = helper.front();
			helper.pop();
			std::cout << temp->Value << '\t';

			if (temp->leftChild)
				helper.push(temp->leftChild);
			if (temp->rightChild)
				helper.push(temp->rightChild);
		}
	}
	std::cout << '\n';
	return *this;
}

template<typename T>
const BinaryTree<T>& BinaryTree<T>::preOrderTraversal(std::vector<T>& preOrder) const
{
	if (this->root == nullptr)
	{
		std::cout << "This binary tree is empty!!! Can not preOrderTraversal!!!\n";
		return *this;
	}

	std::cout << "PreOrderTraversal as belows:\n";
	TreeNode<T>* temp = this->root;
	std::stack<TreeNode<T>*> stk{};

	while (temp != nullptr || !stk.empty())
	{
		//这个循环会持续找左孩子节点直到到达底部
		while (temp)
		{
			//入栈的时候先入根节点,再入左孩子节点,所以打印二叉树的前序遍历
			std::cout << temp->Value << '\t';
			preOrder.emplace_back(temp->Value);
			stk.push(temp);
			temp = temp->leftChild;
		}
		//到底部时temp == nullptr,所以不会进行上面的内层循环
		//持续外层循环并弹出栈顶节点直到该节点有右孩子节点为止(遍历完左子树弹出根节点后开始遍历右子树)
		temp = stk.top();
		stk.pop();
		temp = temp->rightChild;
	}
	std::cout << '\n';
	return *this;
}

template<typename T>
const BinaryTree<T>& BinaryTree<T>::inOrderTraversal(std::vector<T>& inOrder) const
{
	if (this->root == nullptr)
	{
		std::cout << "This binary tree is empty!!! Can not inOrderTraversal!!!\n";
		return *this;
	}

	std::cout << "InOrderTraversal as belows:\n";
	TreeNode<T>* temp = this->root;
	std::stack<TreeNode<T>*> stk{};

	while (temp != nullptr || !stk.empty())
	{
		while (temp)
		{
			stk.push(temp);
			temp = temp->leftChild;
		}
		//先弹出左孩子节点,再弹出根节点,所以打印二叉树的中序遍历
		temp = stk.top();
		stk.pop();
		std::cout << temp->Value << '\t';
		inOrder.emplace_back(temp->Value);
		temp = temp->rightChild;
	}
	std::cout << '\n';
	return *this;
}

template<typename T>
const BinaryTree<T>& BinaryTree<T>::postOrderTraversal(std::vector<T>& postOrder) const
{
	if (this->root == nullptr)
	{
		std::cout << "This binary tree is empty!!! Can not postOrderTraversal!!!\n";
		return *this;
	}

	std::cout << "PostOrderTraversal as belows:\n";
	std::stack<TreeNode<T>*> stk;
	TreeNode<T>* temp = this->root;
	TreeNode<T>* prev = nullptr;

	while (temp != nullptr || !stk.empty())
	{
		while (temp != nullptr)
		{
			stk.push(temp);
			temp = temp->leftChild;
		}
		temp = stk.top();
		stk.pop();

		if (temp->rightChild == nullptr || temp->rightChild == prev)
		{
			std::cout << temp->Value << '\t';
			postOrder.emplace_back(temp->Value);
			prev = temp;
			temp = nullptr;
		}
		else
		{
			stk.push(temp);
			temp = temp->rightChild;
		}
	}
	std::cout << '\n';
	return *this;
}

template<typename T>
BinaryTree<T>& BinaryTree<T>::buildTreeFromPreAndInOrder(std::vector<T>& preOrder, std::vector<T>& inOrder)
{
	if (preOrder.size() == 0)
	{
		return *this;
	}

	this->root = new TreeNode<T>{ preOrder[0] };
	std::stack<TreeNode<T>*> stk;
	stk.push(this->root);
	int inOrderIndex = 0;
	int preOrderSize = preOrder.size();
	for (int i = 1; i < preOrderSize; ++i)
	{
		int preOrderVal = preOrder[i];
		TreeNode<T>* node = stk.top();
		if (node->Value != inOrder[inOrderIndex])
		{
			node->leftChild = new TreeNode<T>(preOrderVal);
			stk.push(node->leftChild);
		}
		else
		{
			while (!stk.empty() && stk.top()->Value == inOrder[inOrderIndex])
			{
				node = stk.top();
				stk.pop();
				++inOrderIndex;
			}
			node->rightChild = new TreeNode<T>{ preOrderVal };
			stk.push(node->rightChild);
		}
	}
	return *this;
}

template<typename T>
BinaryTree<T>& BinaryTree<T>::buildTreeFromInAndPostOrder(std::vector<T>& inOrder, std::vector<T>& postOrder)
{
	if (postOrder.size() == 0)
	{
		return *this;
	}

	this->root = new TreeNode<T>{ postOrder[postOrder.size() - 1] };
	std::stack<TreeNode<T>*> stk;
	stk.push(this->root);
	int inOrderIndex = inOrder.size() - 1;
	int postOrderSize = postOrder.size();
	for (int i = postOrderSize - 2; i >= 0; i--)
	{
		int postOrderVal = postOrder[i];
		TreeNode<T>* node = stk.top();
		if (node->Value != inOrder[inOrderIndex])
		{
			node->rightChild = new TreeNode<T>{ postOrderVal };
			stk.push(node->rightChild);
		}
		else
		{
			while (!stk.empty() && stk.top()->Value == inOrder[inOrderIndex])
			{
				node = stk.top();
				stk.pop();
				inOrderIndex--;
			}
			node->leftChild = new TreeNode<T>{ postOrderVal };
			stk.push(node->leftChild);
		}
	}
	return *this;
}

template<typename T>
std::string serializationFromPreOrder(TreeNode<T>* node)
{
	if (!node)
	{
		return "X";
	}

	std::string left = "(" + serializationFromPreOrder(node->leftChild) + ")";
	std::string right = "(" + serializationFromPreOrder(node->rightChild) + ")";
	return std::to_string(node->Value) + left + right;
}

template<typename T>
std::string serializationFromInOrder(TreeNode<T>* node)
{
	if (!node)
	{
		return "X";
	}

	std::string left = "(" + serializationFromInOrder(node->leftChild) + ")";
	std::string right = "(" + serializationFromInOrder(node->rightChild) + ")";
	return left + std::to_string(node->Value) + right;
}

template<typename T>
std::string serializationFromPostOrder(TreeNode<T>* node)
{
	if (!node)
	{
		return "X";
	}

	std::string left = "(" + serializationFromPostOrder(node->leftChild) + ")";
	std::string right = "(" + serializationFromPostOrder(node->rightChild) + ")";
	return left + right + std::to_string(node->Value);
}

template<typename T>
std::string BinaryTree<T>::serializeFromPreOrder() const
{
	std::cout << "Serialize from pre order as belows:\n";
	return serializationFromPreOrder(this->root);
}

template<typename T>
std::string BinaryTree<T>::serializeFromInOrder() const
{
	std::cout << "Serialize from in order as belows:\n";
	return serializationFromInOrder(this->root);
}

template<typename T>
std::string BinaryTree<T>::serializeFromPostOrder() const
{
	std::cout << "Serialize from post order as belows:\n";
	return serializationFromPostOrder(this->root);
}

template<typename T1, typename T2>
int parseInt(const T1& data, T2& ptr)
{
	int x = 0;
	int sign = 1;
	if (!isdigit(data[ptr]))
	{
		sign = -1;
		++ptr;
	}
	while (isdigit(data[ptr]))
	{
		x = x * 10 + data[ptr++] - '0';
	}
	return x * sign;
}

template<typename T1, typename T2>
TreeNode<T2>* parseSubTreeFromPreOrder(const T1& data, T2& ptr)
{
	++ptr;
	TreeNode<T2>* subTree = parseFromPreOrder(data, ptr);
	++ptr;
	return subTree;
}

template<typename T1, typename T2>
TreeNode<T2>* parseFromPreOrder(const T1& data, T2& ptr)
{
	if (data[ptr] == 'X')
	{
		ptr++;
		return nullptr;
	}

	TreeNode<T2>* cur = new TreeNode<T2>{ 0 };
	cur->Value = parseInt(data, ptr);
	cur->leftChild = parseSubTreeFromPreOrder(data, ptr);
	cur->rightChild = parseSubTreeFromPreOrder(data, ptr);

	return cur;
}

template<typename T>
BinaryTree<T>& BinaryTree<T>::deserializeFromPreOrder(std::string data)
{
	int ptr = 0;
	this->root = parseFromPreOrder(data, ptr);
	return *this;
}

template<typename T1, typename T2>
TreeNode<T2>* parseSubTreeFromInOrder(const T1& data, T2& ptr)
{
	++ptr;
	TreeNode<T2>* subTree = parseFromInOrder(data, ptr);
	++ptr;
	return subTree;
}

template<typename T1, typename T2>
TreeNode<T2>* parseFromInOrder(const T1& data, T2& ptr)
{
	if (data[ptr] == 'X')
	{
		ptr++;
		return nullptr;
	}

	TreeNode<T2>* cur = new TreeNode<T2>{ 0 };
	cur->leftChild = parseSubTreeFromInOrder(data, ptr);
	cur->Value = parseInt(data, ptr);
	cur->rightChild = parseSubTreeFromInOrder(data, ptr);

	return cur;
}

template<typename T>
BinaryTree<T>& BinaryTree<T>::deserializeFromInOrder(std::string data)
{
	int ptr = 0;
	this->root = parseFromInOrder(data, ptr);
	return *this;
}

template<typename T1, typename T2>
TreeNode<T2>* parseSubTreeFromPostOrder(const T1& data, T2& ptr)
{
	++ptr;
	TreeNode<T2>* subTree = parseFromPostOrder(data, ptr);
	++ptr;
	return subTree;
}

template<typename T1, typename T2>
TreeNode<T2>* parseFromPostOrder(const T1& data, T2& ptr)
{
	if (data[ptr] == 'X')
	{
		ptr++;
		return nullptr;
	}

	TreeNode<T2>* cur = new TreeNode<T2>{ 0 };
	cur->leftChild = parseSubTreeFromPostOrder(data, ptr);
	cur->rightChild = parseSubTreeFromPostOrder(data, ptr);
	cur->Value = parseInt(data, ptr);

	return cur;
}

template<typename T>
BinaryTree<T>& BinaryTree<T>::deserializeFromPostOrder(std::string data)
{
	int ptr = 0;
	this->root = parseFromPostOrder(data, ptr);
	return *this;
}

template<typename T>
BinaryTree<T>::~BinaryTree()
{
	if (this->root == nullptr)
	{
		std::cout << "This binary tree is empty!!! No need to delete!!!\n";
		return;
	}

	TreeNode<T>* temp = nullptr;
	std::queue<TreeNode<T>*> helper;
	helper.push(this->root);

	while (!helper.empty())
	{
		temp = helper.front();
		helper.pop();
		if (temp->leftChild)
			helper.push(temp->leftChild);
		if (temp->rightChild)
			helper.push(temp->rightChild);

		delete temp;
		temp = nullptr;
	}
}

int BinaryTreeTest()
{
	BinaryTree<int> tree;
	std::vector<int> preOrder;
	std::vector<int> inOrder;
	std::vector<int> postOrder;
	for (int i = 65; i < 91; i++)
	{
		tree.insert(i);
	}
	tree.preOrderTraversal(preOrder);
	tree.inOrderTraversal(inOrder);
	tree.postOrderTraversal(postOrder);

	BinaryTree<int> TreeSerializeFromPreOrder;
	std::string dataFromPreOrder;
	TreeSerializeFromPreOrder.buildTreeFromPreAndInOrder(preOrder, inOrder);
	std::cout << (dataFromPreOrder = TreeSerializeFromPreOrder.serializeFromPreOrder()) << '\n';

	BinaryTree<int> TreeDeserializeFromPreOrder;
	TreeDeserializeFromPreOrder.deserializeFromPreOrder(dataFromPreOrder);
	TreeDeserializeFromPreOrder.hierarchicalTraversal();

	BinaryTree<int> TreeSerializeFromInOrder;
	std::string dataFromInOrder;
	TreeSerializeFromInOrder.buildTreeFromPreAndInOrder(preOrder, inOrder);
	std::cout << (dataFromInOrder = TreeSerializeFromInOrder.serializeFromInOrder()) << '\n';

	BinaryTree<int> TreeDeserializeFromInOrder;
	TreeDeserializeFromInOrder.deserializeFromInOrder(dataFromInOrder);
	TreeDeserializeFromInOrder.hierarchicalTraversal();

	BinaryTree<int> TreeSerializeFromPostOrder;
	std::string dataFromPostOrder;
	TreeSerializeFromPostOrder.buildTreeFromPreAndInOrder(preOrder, inOrder);
	std::cout << (dataFromPostOrder = TreeSerializeFromPostOrder.serializeFromPostOrder()) << '\n';

	BinaryTree<int> TreeDeserializeFromPostOrder;
	TreeDeserializeFromPostOrder.deserializeFromPostOrder(dataFromPostOrder);
	TreeDeserializeFromPostOrder.hierarchicalTraversal();

	return 0;
}

#include "header.h"
int main()
{
	BinaryTreeTest();
	return 0;
}

测试结果:
在这里插入图片描述
参考:
The C++ Programming Language 3rd Edition, Bjarne.Stroustrup
C++ How to Program 9th Edition, Paul Deitel
Starting Out with C++ Early Objects Seventh Edition, Tony Gaddis, Judy Walters, Godfrey Muganda
C++ Templates The Complete Guide SECOND EDITION, David Vandevoorde, Nicolai M. Josuttis, Douglas Gregor
102. 二叉树的层序遍历
144. 二叉树的前序遍历
94. 二叉树的中序遍历
145. 二叉树的后序遍历
105. 从前序与中序遍历序列构造二叉树
106. 从中序与后序遍历序列构造二叉树
LCR 156. 序列化与反序列化二叉树

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值