相信很多初学数据结构的小朋友都觉得二叉树难以理解,这种数据结构比数组、链表等更抽象,我们很难利用本地编译器构造一棵二叉树、看到一棵二叉树的结构。有时在网上刷题(比如说力扣,我经常用这个),题目输入或输出为一棵二叉树,只能通过网上的编译器完成二叉树的输入和可视化:(图来自力扣编译器)
为了方便本地调试,我做了一个程序完成二叉树的构建(输入层序遍历序列,得到构建好的二叉树的根结点),以及在控制台上输入根节点打印二叉树。
代码段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°)