二叉树的构建和可视化(C++)

相信很多初学数据结构的小朋友都觉得二叉树难以理解,这种数据结构比数组、链表等更抽象,我们很难利用本地编译器构造一棵二叉树、看到一棵二叉树的结构。有时在网上刷题(比如说力扣,我经常用这个),题目输入或输出为一棵二叉树,只能通过网上的编译器完成二叉树的输入和可视化:(图来自力扣编译器)

为了方便本地调试,我做了一个程序完成二叉树的构建(输入层序遍历序列,得到构建好的二叉树的根结点),以及在控制台上输入根节点打印二叉树。

代码段1:引头文件,定义TreeNode结构体(和力扣上的定义完全一样)

#include<iostream>
#include<vector>
#include<cstring>
#include<string>
#include<queue>
#include<unordered_map>
using namespace std;
#define nulptr -2018767868
//Definition for a binary tree node.(From Leetcode)
struct TreeNode {
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode() : val(0), left(nullptr), right(nullptr) {}
	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
	TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};
typedef struct TreeNode treenode;

代码段2:二叉树的构造功能

bool treemake(vector<int> letra,treenode* &root);函数输入为

1、装有层序遍历序列的vector数组

2、根节点的引用,构造好的树会接在这个根节点上

bool类型返回值表示构造是否成功

bool readtree(treenode*& root);用于从控制台读取装有层序遍历序列的vector数组

读取后调用treemake函数构造二叉树

bool类型返回值同样表示构造是否成功

//二叉树构造
bool treemake(vector<int> letra,treenode* &root)//Please input the level order traversal of the binary tree
{
	root = NULL;
	if (letra.size() == 0)
		return true;
	queue<treenode*> que;
	vector<int>::iterator it = letra.begin();
	if (*it == nulptr)
	{
		if (letra.size() >= 2)
			return false;
		else
			return true;
	}
	root = new treenode;
	root->val = *it;
	que.push(root);
	while (!que.empty())
	{
		int if_stop = 0;
		treenode* cur = que.front();
		que.pop();
		for (int i = 0; i < 2; i++)
		{
			it++;
			if (it == letra.end())
			{
				if_stop = 1;
				break;
			}
			else
			{
				treenode* tnode;
				if (*it != nulptr)
				{
					tnode = new treenode;
					tnode->val = *it;
					que.push(tnode);
				}
				else
					tnode = NULL;
				if (i == 0)
					cur->left = tnode;
				else
					cur->right = tnode;
			}
		}
		if (if_stop)
			break;
	}
	if (!que.empty())
		return true;
	else
	{
		if (it != letra.end())
		it++;
		for (; it != letra.end(); it++)
		{
			if (*it != nulptr)
				return false;
		}
		return true;
	}
}
bool readtree(treenode*& root)
{
	cout << "请输入生成树的层序遍历" << endl;
	//cout << "输入格式样例:[3,9,20,null,null,15,7]" << endl;
	string read;
	cin >> read;
	int slen = read.size();
	if (read[0] != '[' || read[slen - 1] != ']')
		return false;
	string temp = "";
	vector<int> letra;
	for (int i = 1; i < slen; i++)
	{
		if (read[i] != ','&& read[i] != ']')
		{
			temp += read[i];
		}
		else
		{
			if (temp == "null")
			{
				letra.emplace_back(nulptr);
			}
			else if(temp.size()!=0)
			{
				int num = stoi(temp);
				letra.emplace_back(num);
			}
			temp = "";
		}
	}
	return treemake(letra, root);
}

代码段3:二叉树的打印功能

只需在void printtree(treenode* root);输入一棵二叉树的根结点,就能在控制台上看到二叉树

//二叉树打印
int tree_depth;
void count_tree_depth(treenode * node,int deep)
{
	tree_depth = deep > tree_depth ? deep : tree_depth;
	if (node->left != NULL)
		count_tree_depth(node->left, deep + 1);
	if (node->right != NULL)
		count_tree_depth(node->right, deep + 1);
}
void printtree(treenode* root)
{
	//确定二叉树深度
	tree_depth = -1;
	if(root!=NULL)
		count_tree_depth(root, tree_depth+1);
	else
	{
		cout << "****" << endl << "NULL" << endl << "****" << endl;
		return;
	}
	//层序遍历二叉树
	vector<vector<pair<int,int>>> node;
	node.resize(tree_depth+1);
	queue<pair<treenode*, int>> lque;
	lque.push(make_pair(root, 0));
	treenode* Nuptr = NULL;
	while (1)
	{
		treenode* cur = lque.front().first;
		int floor = lque.front().second;
		if (floor == tree_depth + 1)
			break;
		lque.pop();
		if (cur == NULL)
		{
			lque.push(make_pair(Nuptr, floor + 1));
			lque.push(make_pair(Nuptr, floor + 1));
			node[floor].emplace_back(make_pair(nulptr,0));
			continue;
		}
		if (cur->left != NULL)
			lque.push(make_pair(cur->left, floor + 1));
		else
			lque.push(make_pair(Nuptr, floor + 1));
		if (cur->right != NULL)
			lque.push(make_pair(cur->right, floor + 1));
		else
			lque.push(make_pair(Nuptr, floor + 1));
		node[floor].emplace_back(make_pair(cur->val,0));
	}
	//构造最后一列
	unordered_map<int,vector< pair<int, int>>> hash;
	vector<pair<int,int>>::iterator it1;
	for (it1 = node[tree_depth].begin(); it1 != node[tree_depth].end(); it1++)
	{
		int num1 = it1 - node[tree_depth].begin() + 1;
		if (num1 % 2 == 1)
		{
			hash[(3 * num1 - 1) / 2].emplace_back(make_pair((*it1).first, tree_depth));
			(*it1).second = (3 * num1 - 1) / 2;
		}
		else
		{
			hash[(3 * num1) / 2].emplace_back(make_pair((*it1).first, tree_depth));
			(*it1).second = (3 * num1) / 2;
		}
	}
	it1--;
	int maxline = (*it1).second;
	//构造其余列
	vector<pair<int, int>>::iterator it2;
	for (int i = tree_depth - 1 ; i >= 0; i--)
	{
		it1 = node[i + 1].begin();
		it2 = node[i].begin();
		while(it1!=node[i+1].end())
		{
			int line1 = (*it1).second;
			it1++;
			int line2 = (*it1).second;
			it1++;
			if (it2 - node[i].begin() < node[i].size()/2)//向上取整
				(*it2).second = (line1 + line2 + 1) / 2;
			else//向下取整
				(*it2).second = (line1 + line2) / 2;
			hash[(*it2).second].emplace_back(make_pair((*it2).first, i));
			it2++;
		}
	}
	cout << "***************" << endl;
	for (int i = maxline; i >= 1; i--)
	{
		vector<pair<int, int>> vep = hash[i];
		int col = 0;
		int vsize = vep.size();
		for (int k = vsize - 1; k >= 0; k--)
		{
			for (; col < vep[k].second; col++)
				cout << "\t";
			if (vep[k].first != nulptr)
				cout << vep[k].first;
			else
				cout << "NULL";
		}
		cout << endl;
	}
	cout << "***************" << endl;
}

代码段4:下面加上main函数试一试效果。

先从控制台读取层序遍历序列,如果构造成功,就打印二叉树

int main()
{
	treenode* root;
	bool flag = readtree(root);
	if (flag)
	{
		cout << "二叉树生成成功" << endl;
		printtree(root);
	}
	else
		cout << "二叉树生成失败" << endl;
	return 0;
}

效果:整棵树是横着打印的(相当于逆时针旋转了90°)

 

 

 

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值