数据结构、C/C++——实现一个STL风格的简单二叉树类模板,支持先中后层序遍历以及根据遍历重建二叉树方法

简介

简单的二叉数类,支持结构化字符串和中序遍历+任意一种其他遍历方式来建立一颗STL风格的二叉树。

所谓结构化字符串,即以ROOT[(LEFT[,RIGHT])]来表示一个节点和其左右子树结构,无右子树可省略逗号,无子树可省略括号,如0(1(,2),3(4,5(6(7,8),9)))中根节点为0,左子树为1(,2),右子树为3(4,5(6(7,8),9))。结构如下:
二叉树

测试代码
int main()
{
	BinTree<string> bts("0(1(3,4),2(5,6))", vector<string>{"a", "b", "c", "d", "e", "f", "g"});
    cout << "bts:" << endl; bts.show(); // 左转90°打印树
	BinTree<uint> bt1("1(2(4),3(5(,7),6))");
    cout << "bt1:" << endl; bt1.show();
	BinTree<uint> bt2(bt1); // 拷贝构造
	BinTree<uint> bt3, bt4, bt5;
	bt3.fromPreorder(bt1.inorder(), bt1.preorder()); // 中序 + 先序 重建二叉树
	bt4.fromPostorder(bt2.inorder(), bt2.postorder()); // 中序 + 后序 重建二叉树
	bt5.fromLevelorder(bt3.inorder(), bt3.levelorder()); // 中序 + 层序 重建二叉树
	cout << "bt1 == bt2: " << (bt1 == bt2) << endl;
	cout << "bt2 == bt3: " << (bt2 == bt3) << endl;
	cout << "bt3 == bt4: " << (bt3 == bt4) << endl;
	cout << "bt4 == bt5: " << (bt4 == bt5) << endl;
	cout << "levelorder: ";
	for (cosnt auto& x : bt2.levelorder()) // 层序遍历
		cout << x << ' ';
	cout << endl;
	cout << "preorder: ";
	for (cosnt auto& x : bt3.preorder()) // 先序遍历
		cout << x << ' ';
	cout << endl;
	cout << "inorder: ";
	for (cosnt auto& x : bt4.inorder()) // 中序遍历
		cout << x << ' ';
	cout << endl;
	cout << "postorder: ";
	for (cosnt auto& x : bt5.postorder()) // 后序遍历
		cout << x << ' ';
	cout << endl;
	cout << "depth: " << bt1.depth() << endl; // 树的高度
	cout << "size: " << bt1.size() << endl; // 树的结点数
    return 0;
}
测试效果

测试效果

代码
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<tuple>
#include<unordered_map>
#include<iostream>
using namespace std;
typedef unsigned int uint;

template<typename T>
struct TreeNode {
	uint id;
	T val;
	TreeNode<T>* left;
	TreeNode<T>* right;
	TreeNode(uint id, T val) :id(id), val(val), left(nullptr), right(nullptr) {}
	~TreeNode() {
		if (left != nullptr) delete left;
		if (right != nullptr) delete right;
	}
};

template<typename T>
class BinTree {
private:
	TreeNode<T>* root;
	static bool isVaild(const string& treestr) { // 判断格式字符串是否合法
		uint count = 0;
		for (auto c : treestr) {
			if (c == '(') ++count;
			else if (c == ')') --count;
			if (count < 0) return false;
		}
		if (count == 0) return true;
		else return false;
	}
	static uint treestrSplit(const string& treestr, string& left, string& right) { // 分割格式字符串
		auto index = treestr.find('(');
		if (index == string::npos) {
			left.clear();
			right.clear();
			return stoi(treestr);
		}
		uint count = 0;
		auto i = index + 1;
		for (;i < treestr.size();++i) {
			if (treestr[i] == '(') ++count;
			else if (treestr[i] == ')') --count;
			else if (treestr[i] == ',' && count == 0) {
				left = treestr.substr(index + 1, i - index - 1);
				right = treestr.substr(i + 1, treestr.size() - i - 2);
				break;
			}
		}
		if (i == treestr.size()) {
			left = treestr.substr(index + 1, treestr.size() - index - 2);
			right.clear();
		}
		return stoi(treestr.substr(0, index));
	}
	static TreeNode<T>* buildTree(const string& treestr, const vector<T>& data) { // 根据格式字符串递归构建二叉树
		if (treestr.empty()) return nullptr;
		string left, right;
		uint id = treestrSplit(treestr, left, right);
		T val;
		if (data.empty() && typeid(T) == typeid(uint)) val = id;
		else val = data[id];
		TreeNode<T>* node = new TreeNode<T>(id, val);
		node->left = buildTree(left, data);
		node->right = buildTree(right, data);
		return node;
	}
	static string buildStr(TreeNode<T>* node) { // 根据二叉树递归构建格式字符串
		if (node == nullptr) return "";
		string str = to_string(node->id), left = buildStr(node->left), right = buildStr(node->right);
		if (!left.empty()) {
			str += '(';
			str += left;
			if (!right.empty()) {
				str += ',';
				str += right;
			}
			str += ')';
		}
		else if (!right.empty()) {
			str += "(,";
			str += right + ')';
		}
		return str;
	}
	static TreeNode<T>* copyTree(const TreeNode<T>* other) { // 根据二叉树递归复制二叉树
		if (other == nullptr) return nullptr;
		TreeNode<T>* node = new TreeNode<T>(other->id, other->val);
		node->left = copyTree(other->left);
		node->right = copyTree(other->right);
		return node;
	}
	static TreeNode<T>* buildByPre(int low, int high, unordered_map<uint, uint> inorder, vector<uint>& preorder, vector<T>& data) {
		// 根据中序先序遍历递归构造二叉树
		if (low > high) return nullptr;
		uint id = preorder.back();
		preorder.pop_back();
		T val;
		if (data.empty() && typeid(T) == typeid(uint)) val = id;
		else val = data[id];
		TreeNode<T>* node = new TreeNode<T>(id, val);
		uint index = inorder[node->id];
		node->left = buildByPre(low, index - 1, inorder, preorder, data);
		node->right = buildByPre(index + 1, high, inorder, preorder, data);
		return node;
	}
	static TreeNode<T>* buildByPost(int low, int high, unordered_map<uint, uint> inorder, vector<uint>& postorder, vector<T>& data) {
		// 根据中序后序遍历递归构造二叉树
		if (low > high) return nullptr;
		uint id = postorder.back();
		postorder.pop_back();
		T val;
		if (data.empty() && typeid(T) == typeid(uint)) val = id;
		else val = data[id];
		TreeNode<T>* node = new TreeNode<T>(id, val);
		uint index = inorder[node->id];
		node->right = buildByPost(index + 1, high, inorder, postorder, data);
		node->left = buildByPost(low, index - 1, inorder, postorder, data);
		return node;
	}
	static void levelToPre(int low, int high, const vector<uint>& inorder, const vector<uint>& levelorder, vector<uint>& preorder) {
		// 根据中序层序遍历求出前序遍历
		for (auto n : levelorder) {
			for (auto i = low; i <= high; ++i) {
				if (inorder[i] == n) {
					preorder.push_back(n);
					if (i > low) levelToPre(low, i - 1, inorder, levelorder, preorder);
					if (i < high) levelToPre(i + 1, high, inorder, levelorder, preorder);
					return;
				}
			}
		}
	}
	static uint getDepth(const TreeNode<T>* node) { // 递归计算树高
		if (node == nullptr) return 0;
		return max(getDepth(node->left), getDepth(node->right)) + 1;
	}
	static uint getSize(const TreeNode<T>* node) { // 递归计算结点数
		if (node == nullptr) return 0;
		return getSize(node->left) + getSize(node->right) + 1;
	}
	static bool eq(const TreeNode<T>* node, const TreeNode<T>* other) { // 递归比较二叉树
		if (node == other) return true;
		if (node == nullptr || other == nullptr) return false;
		if (node->val != other->val) return false;
		return eq(node->left, other->left) && eq(node->right, other->right);
	}
public:
	BinTree() { root = nullptr; }
	BinTree(const string& treestr, const vector<T>& data = {}) { // 根据格式字符串和值列表(可选)构建二叉树
		if (isVaild(treestr)) root = buildTree(treestr, data);
		else throw treestr + " is not a vaild treestr.";
	}
	BinTree(BinTree<T>& other) { // 拷贝构造函数
		root = copyTree(other.getRoot());
	}
	~BinTree() {
		if (root != nullptr) delete root;
	}
	bool fromPreorder(vector<uint> inorder, vector<uint> preorder, vector<T> data = {}) { 
		// 根据中序遍历 + 先序遍历构建二叉树
		if (root != nullptr) return false;
		unordered_map<uint, uint> inorder_map;
		reverse(preorder.begin(), preorder.end());
		for (uint i = 0; i < inorder.size(); ++i)
			inorder_map[inorder[i]] = i;
		root = buildByPre(0, preorder.size() - 1, inorder_map, preorder, data);
		return true;
	}
	bool fromPostorder(vector<uint> inorder, vector<uint> postorder, vector<T> data = {}) {
		// 根据中序遍历 + 后序遍历构建二叉树
		if (root != nullptr) return false;
		unordered_map<uint, uint> inorder_map;
		for (uint i = 0; i < inorder.size(); ++i)
			inorder_map[inorder[i]] = i;
		root = buildByPost(0, postorder.size() - 1, inorder_map, postorder, data);
		return true;

	}
	bool fromLevelorder(vector<uint> inorder, vector<uint> levelorder, vector<T> data = {}) {
		// 根据中序遍历 + 层序遍历构建二叉树
		if (root != nullptr) return false;
		vector<uint> preorder;
		levelToPre(0, inorder.size() - 1, inorder, levelorder, preorder);
		return fromPreorder(inorder, preorder, data);
	}
	string getTreestr() { // 返回二叉树的格式字符串
		return buildStr(root);
	}
	const TreeNode<T>* getRoot() { // 返回二叉树根节点
		return root;
	}
	uint depth() { // 返回二叉数高度
		return getDepth(root);
	}
	uint size() { // 返回二叉数结点数
		return getSize(root);
	}
	void show() { // 左转90°打印二叉树结点
		stack<uint> levels;
		stack<TreeNode<T>*> nodes;
		TreeNode<T>* node = root;
		uint level = 0;
		while (node != nullptr || !nodes.empty()) {
			if (node != nullptr) {
				levels.push(level);
				nodes.push(node);
				++level;
				node = node->right;
			}
			else {
				level = levels.top();
				levels.pop();
				node = nodes.top();
				nodes.pop();
				cout << string(3 * level, ' ');
				cout << node->val << endl;
				node = node->left;
				++level;
			}
		}
	}
	vector<T> levelorder() { // 返回层序遍历二叉树的vector<val>
		if (root == nullptr) return {};
		vector<T> res;
		queue<TreeNode<T>*> que;
		TreeNode<T>* node;
		que.push(root);
		while (!que.empty()) {
			node = que.front();
			que.pop();
			if (node->left != nullptr) que.push(node->left);
			if (node->right != nullptr) que.push(node->right);
			res.push_back(node->val);
		}
		return res;
	}
	vector<T> preorder() { // 返回先序遍历二叉树的vector<val>
		if (root == nullptr) return {};
		vector<T> res;
		stack<TreeNode<T>*> stk;
		TreeNode<T>* node;
		stk.push(root);
		while (!stk.empty()) {
			node = stk.top();
			stk.pop();
			if (node->right != nullptr) stk.push(node->right);
			if (node->left != nullptr) stk.push(node->left);
			res.push_back(node->val);
		}
		return res;
	}
	vector<T> inorder() { // 返回中序遍历二叉树的vector<val>
		if (root == nullptr) return {};
		vector<T> res;
		stack<TreeNode<T>*> stk;
		TreeNode<T>* node = root;
		while (node != nullptr || !stk.empty()) {
			while (node != nullptr) {
				stk.push(node);
				node = node->left;
			}
			node = stk.top();
			stk.pop();
			res.push_back(node->val);
			node = node->right;
		}
		return res;
	}
	vector<T> postorder() { // 返回后序遍历二叉树的vector<val>
		if (root == nullptr) return {};
		vector<T> res;
		stack<TreeNode<T>*> stk;
		TreeNode<T>* node;
		stk.push(root);
		while (!stk.empty()) {
			node = stk.top();
			stk.pop();
			if (node->left != nullptr) stk.push(node->left);
			if (node->right != nullptr) stk.push(node->right);
			res.push_back(node->val);
		}
		reverse(res.begin(), res.end());
		return res;
	}
	bool operator== (BinTree<T>& other) { // 判断二叉树相等(仅判断对应结点val是否相等,无视结点id)
		return eq(root, other.getRoot());
	}
	bool operator!= (BinTree<T>& other) {
		return !eq(root, other.getRoot());
	}
};

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值