2014-01-15 109 views
1

我正在做一个任务,我需要创建一个二叉树。我有正确的二进制逻辑,但我很难在如何以及在哪里创建树。下面的屏幕截图是我目前的输出结果,我想将它制作成树形的形式,其顶部的根位于下方。此时如果水平线变得更容易,我甚至会在这一点上解决这个问题。C++在控制台问题中绘制二叉树

C++ binary tree current output

#include <iostream> 
#include <string> 

using namespace std; 

class TreeNode 
{ 
public: 
    void insert_node(TreeNode* new_node); 
    void print_nodes() const; 
    bool find(string value) const; 
private: 
    string data; 
    TreeNode* left; 
    TreeNode* right; 
friend class BinarySearchTree; 
}; 

class BinarySearchTree 
{ 
public: 
    BinarySearchTree(); 
    void insert(string data); 
    void erase(string data); 
    int count(string data) const; 
    void print() const; 
private: 
    TreeNode* root; 
}; 

/* 
    BinarySearchTree Default constructor 
*/ 

BinarySearchTree::BinarySearchTree() 
{ 
    root = NULL; 
} 

void BinarySearchTree::print() const 
{ 
    if (root != NULL) 
    { 
     root->print_nodes(); 
    } 
} 

void BinarySearchTree::insert(string data) 
{ 
    // Creates a new node and sets values 
    TreeNode* new_node = new TreeNode; 
    // Saves data to new_node and pointers to NULL 
    new_node->data = data; 
    new_node->left = NULL; 
    new_node->right = NULL; 
    // sets root as node saved above 
    if (root == NULL) 
    { 
     root = new_node; 
    } 
    /* 
     If root has has been set then determine how to link new_node. 
     root is the parent node and new_node will be the child of root 
    */ 
    else root->insert_node(new_node); 
} 

void TreeNode::insert_node(TreeNode* new_node) 
{ 
    // this-> referrs to root node 
    if (new_node->data < this->data) 
    { 
     // Sets left node of root to 
     // point to new_node 
     if (this->left == NULL) 
      { 
       this->left = new_node; 
      } 
     // inserts a new node onto root->left 
     else this->left->insert_node(new_node); 
    } 
    else if (this->data < new_node->data) 
    { 
     if (this->right == NULL) 
      { 
       // inserts a new node onto root->right 
       this->right = new_node; 

      } 
     else this->right->insert_node(new_node); 
    } 
} 

int BinarySearchTree::count(string data) const 
{ 
    if (root == NULL) return 0; 
    else if (root->find(data)) return 1; 
    else return 0; 
} 

void BinarySearchTree::erase(string data) 
{ 
    // Find node to be removed 

    TreeNode* to_be_removed = root; 
    TreeNode* parent = NULL; 
    bool found = false; 
    while (!found && to_be_removed != NULL) 
    { 
     if (to_be_removed->data < data) 
     { 
     parent = to_be_removed; 
     to_be_removed = to_be_removed->right; 
     } 
     else if (data < to_be_removed->data) 
     { 
     parent = to_be_removed; 
     to_be_removed = to_be_removed->left; 
     } 
     else found = true; 
    } 

    if (!found) return; 

    // to_be_removed contains data 

    // If one of the children is empty, use the other 

    if (to_be_removed->left == NULL || to_be_removed->right == NULL) 
    { 
     TreeNode* new_child; 
     if (to_be_removed->left == NULL) 
     new_child = to_be_removed->right; 
     else 
     new_child = to_be_removed->left; 
     if (parent == NULL) // Found in root 
     root = new_child; 
     else if (parent->left == to_be_removed) 
     parent->left = new_child; 
     else 
     parent->right = new_child; 
     return; 
    } 

    // Neither subtree is empty 

    // Find smallest element of the right subtree 

    TreeNode* smallest_parent = to_be_removed; 
    TreeNode* smallest = to_be_removed->right; 
    while (smallest->left != NULL) 
    { 
     smallest_parent = smallest; 
     smallest = smallest->left; 
    } 

    // smallest contains smallest child in right subtree 

    // Move contents, unlink child 
    to_be_removed->data = smallest->data; 
    if (smallest_parent == to_be_removed) 
     smallest_parent->right = smallest->right; 
    else 
     smallest_parent->left = smallest->right; 
} 

bool TreeNode::find(string value) const 
{ 
    if (value < data) 
    { 
     if (left == NULL) return false; 
     else return left->find(value); 
    } 
    else if (data < value) 
    { 
     if (right == NULL) return false; 
     else return right->find(value); 
    } 
    else 
     return true; 
} 

void TreeNode::print_nodes() const 
{ 

    if (this->right != NULL) 
    { 
     cout << data << "\n" << "\\" << "\n" << this->right->data << " " << "\n"; 
     this->right->print_nodes(); 


     if (this->left != NULL) 
     { 
      cout << data << "\n" << "/" << "\n" << this->left->data << "\n"; 
      this->left->print_nodes(); 
     } 
    } 

} 

int main() 
{ 
    BinarySearchTree t; 
    t.insert("D"); 
    t.insert("B"); 
    t.insert("A"); 
    t.insert("C"); 
    t.insert("F"); 
    t.insert("E"); 
    t.insert("I"); 
    t.insert("G"); 
    t.insert("H"); 
    t.insert("J"); 

    t.print(); 

    cout << "\n \n"; 

    cout << "\n \n"; 

    system("pause"); 
    return 0; 
} 

回答

1

有很多方法可以做到这一点。这里是一个:

A 
|-B 
| |-C 
| | |-H 
| | `-I 
| `-D 
| |-F 
| `-G 
`-E 

这里有儿童B和E. B有C和D等...

那么,如何才能把这事办成?这里是伪代码:

Let S = {} (an empty global set of integers) 

procedure indent(level) 
for i in [0..level) 
    if i \in S print "| " 
    else print " " 

procedure tee(level) 
indent(level) 
print("|-") 
S = S + { level } 

procedure ell(level) 
indent(level) 
print("`-") 
S = S - { level } 

procedure print(node, level) 
if node is null 
    print("[null]" with newline) // only prints when 1 child is missing 
else 
    print(node label with newline) 
    if node has any children 
    tee(level) 
    print(node.left, level + 1) 
    ell(level) 
    print(node.right, level + 1) 

设置跟踪哪些列需要垂直条。每个“三通”形状开始一个垂直酒吧。每个“椭圆”形状在同一列中结束。

该集合可以是布尔值(字符)的数组,最初通过将其设置为零而最初为空。其余几乎是一条线对线转换为C.

我在31个节点的完整树上的快速结果。

L0 
|-L1 
| |-L2 
| | |-L3 
| | | |-L4 
| | | `-L5 
| | `-L6 
| | |-L7 
| | `-L8 
| `-L9 
| |-L10 
| | |-L11 
| | `-L12 
| `-L13 
|  |-L14 
|  `-L15 
`-L16 
    |-L17 
    | |-L18 
    | | |-L19 
    | | `-L20 
    | `-L21 
    | |-L22 
    | `-L23 
    `-L24 
    |-L25 
    | |-L26 
    | `-L27 
    `-L28 
     |-L29 
     `-L30 

对于普通观众这是值得指出的是,这一作品将与孩子标签N叉树(如编译器中抽象语法树)。将子女姓名参数添加到elltee,并为每个孩子呼叫tee,但最后一个孩子的姓名仍为ell

2

没有给你完整的答案(这毕竟是一个分配)我可以指出你一些参考和搜索字词。你想要完成的事情很难用递归。你可能更喜欢做一个breadth first traversal

你基本上使用另一个容器在树中从右到左的顺序添加节点。一旦完成,您将在第二个容器上进行迭代并打印值。由于您可以计算层数,因此使用空格格式化输出以便缩进左侧和右侧节点将很容易。

它也可以在一次遍历中完成(仍然使用第二个容器),但算法稍微复杂一些。