动手构建二叉树的可视化工具
前言
承接N叉树的可视化,可能二叉树的可视化比N叉树的用途更广,这里就不再赘述其原理了,只简单做了注释,原理和N叉树差不多,只是需要特殊处理空节点。
对原理和实现感兴趣的可以跳转至前文
绘制效果展示:
代码实现
注意:二叉可视化树的节点需要自己构建和初始化。
//数据结构:
typedef struct GraphBinaryNode{
GraphBinaryNode* leftChild;
GraphBinaryNode* rightChild;
int leftLength;
int rightLength;
string content;
int pos;
}*GraphBinaryTree
//二叉可视化树的初始化:
void calLength(GraphBinaryTree root){
if(root->leftChild != nullptr){
calLength(root->leftChild);
root->leftLength = root->leftChild->leftLength + root->leftChild->rightLength + 1;
}else{
//一边为空,但父节点信息的绘制需要占据空间
root->leftLength = root->content.size() / 2 + 1;
}
if(root->rightChild != nullptr){
calLength(root->rightChild);
root->rightLength = root->rightChild->leftLength + root->rightChild->rightLength + 1;
}else{
//一边为空,但父节点信息的绘制需要占据空间
root->rightLength = root->content.size() / 2 + 1;
}
}
void calPosition(GraphBinaryTree root){
int pos = root->pos;
if(root->leftChild != nullptr){
root->leftChild->pos = pos;
calPosition(root->leftChild);
}
//隔断所占的空间
pos += root->leftLength + 1;
if(root->rightChild != nullptr){
root->rightChild->pos = pos;
calPosition(root->rightChild);
}
}
//绘制节点信息及辅助线:
string drawNode(GraphBinaryNode* node){
int length, offset = node->content.size() / 2 + 1;;
string blank;
if(node->leftChild != nullptr && node->rightChild != nullptr){
length = node->leftLength + node->rightLength + 1;
if(length / 2 - offset > 0){
blank = string(length / 2 - offset, ' ');
}
}else if(node->leftChild == nullptr){
blank = "";
}else if(node->rightChild == nullptr){
if(node->leftLength - offset > 0){
blank = string(node->leftLength - offset, ' ');
}
}
return blank + "(" + node->content + ")";
}
string drawLine(GraphBinaryNode* node){
if(node->leftChild == nullptr && node->rightChild == nullptr) return "";
string line;
if(node->leftChild != nullptr){
string blank, segment;
GraphBinaryNode* leftChild = node->leftChild;
//辅助线的绘制比较复杂,不仅取决于孩子的情况,还取决于孙子的情况,需要枚举多个情况
if((leftChild->leftChild != nullptr && leftChild->rightChild != nullptr)
|| (leftChild->leftChild == nullptr && leftChild->rightChild == nullptr)){
blank = string(node->leftLength / 2, ' ');
segment = string(node->leftLength / 2, '-');
}else if(leftChild->leftChild == nullptr){
blank = string(leftChild->content.size() / 2 + 1, ' ');
segment = string(leftChild->rightLength, '-');
}else if(leftChild->rightChild == nullptr){
blank = string(node->leftLength - leftChild->content.size() / 2 - 2, ' ');
segment = string(leftChild->rightLength, '-');
}
line += blank + '+' + segment;
}else{
line += string(node->leftLength, ' ');
}
line += '-';
if(node->rightChild != nullptr){
string blank, segment;
GraphBinaryNode* rightChild = node->rightChild;
//辅助线的绘制比较复杂,不仅取决于孩子的情况,还取决于孙子的情况,需要枚举多个情况
if((rightChild->leftChild != nullptr && rightChild->rightChild != nullptr)
|| (rightChild->leftChild == nullptr && rightChild->rightChild == nullptr)){
blank = string(node->rightLength / 2, ' ');
segment = string(node->rightLength / 2, '-');
}else if(rightChild->leftChild == nullptr){
blank = string(rightChild->rightLength, ' ');
segment = string(rightChild->content.size() / 2 + 1, '-');
}else if(rightChild->rightChild == nullptr){
blank = string(rightChild->leftLength - rightChild->content.size() / 2, ' ');
segment = string(node->rightLength - rightChild->content.size() / 2 - 2, '-');
}
line += segment + '+' + blank;
}else{
line += string(node->rightLength, ' ');
}
return line;
}
//绘制主函数:
string drawGraphTree(GraphBinaryTree root){
calLength(root);
calPosition(root);
vector<GraphBinaryNode*> level{root};
string graphTree;
while(level.size() > 0){
string row1, row2;
vector<GraphBinaryNode*> nextLevel;
for(GraphBinaryNode* node : level){
string nodeInfo = drawNode(node);
string line = drawLine(node);
string fix1, fix2;
if(row1.size() < node->pos){
fix1 = string(node->pos - row1.size(), ' ');
}
if(row2.size() < node->pos){
fix2 = string(node->pos - row2.size(), ' ');
}
nodeInfo = fix1 + nodeInfo;
line = fix2 + line;
if(node->leftChild != nullptr) nextLevel.push_back(node->leftChild);
if(node->rightChild != nullptr) nextLevel.push_back(node->rightChild);
row1 += nodeInfo;
row2 += line;
}
level = nextLevel;
row1 += '\n';
row2 += '\n';
graphTree += row1 + row2;
}
return graphTree;
}
int main(){
//对于构建好的二叉树
GraphBinaryTree root;
//构建二叉树...
cout << drawGraphTree(root) << endl;
return 0;
}
评论 |
0条评论