在python

时间:2015-12-01 04:56:16

标签: python python-3.4

我想以下列方式打印我的二叉树:

                   10

               6        12

             5   7    11  13 

我编写了用于插入节点的代码,但无法编写用于打印树的代码。所以请帮忙。我的代码是:

class Node:
    def __init__(self,data):
       self.data=data
       self.left=None
       self.right=None
       self.parent=None

class binarytree:
   def __init__(self):
     self.root=None
     self.size=0

   def insert(self,data):
     if self.root==None:
        self.root=Node(data)

    else:
        current=self.root
        while 1:
            if data < current.data:
                if current.left:
                    current=current.left
                else:
                    new=Node(data)
                    current.left=new
                    break;
            elif data > current.data:
                if current.right:
                    current=current.right
                else:
                    new=Node(data)
                    current.right=new
                    break;
            else:
                break



 b=binarytree()  

8 个答案:

答案 0 :(得分:9)

Here's my attempt, using recursion, and keeping track of the size of each node and the size of children.

class BstNode:

    def __init__(self, key):
        self.key = key
        self.right = None
        self.left = None

    def insert(self, key):
        if self.key == key:
            return
        elif self.key < key:
            if self.right is None:
                self.right = BstNode(key)
            else:
                self.right.insert(key)
        else: # self.key > key
            if self.left is None:
                self.left = BstNode(key)
            else:
                self.left.insert(key)

    def display(self):
        lines, _, _, _ = self._display_aux()
        for line in lines:
            print(line)

    def _display_aux(self):
        """Returns list of strings, width, height, and horizontal coordinate of the root."""
        # No child.
        if self.right is None and self.left is None:
            line = '%s' % self.key
            width = len(line)
            height = 1
            middle = width // 2
            return [line], width, height, middle

        # Only left child.
        if self.right is None:
            lines, n, p, x = self.left._display_aux()
            s = '%s' % self.key
            u = len(s)
            first_line = (x + 1) * ' ' + (n - x - 1) * '_' + s
            second_line = x * ' ' + '/' + (n - x - 1 + u) * ' '
            shifted_lines = [line + u * ' ' for line in lines]
            return [first_line, second_line] + shifted_lines, n + u, p + 2, n + u // 2

        # Only right child.
        if self.left is None:
            lines, n, p, x = self.right._display_aux()
            s = '%s' % self.key
            u = len(s)
            first_line = s + x * '_' + (n - x) * ' '
            second_line = (u + x) * ' ' + '\\' + (n - x - 1) * ' '
            shifted_lines = [u * ' ' + line for line in lines]
            return [first_line, second_line] + shifted_lines, n + u, p + 2, u // 2

        # Two children.
        left, n, p, x = self.left._display_aux()
        right, m, q, y = self.right._display_aux()
        s = '%s' % self.key
        u = len(s)
        first_line = (x + 1) * ' ' + (n - x - 1) * '_' + s + y * '_' + (m - y) * ' '
        second_line = x * ' ' + '/' + (n - x - 1 + u + y) * ' ' + '\\' + (m - y - 1) * ' '
        if p < q:
            left += [n * ' '] * (q - p)
        elif q < p:
            right += [m * ' '] * (p - q)
        zipped_lines = zip(left, right)
        lines = [first_line, second_line] + [a + u * ' ' + b for a, b in zipped_lines]
        return lines, n + m + u, max(p, q) + 2, n + u // 2


import random

b = BstNode(50)
for _ in range(50):
    b.insert(random.randint(0, 100))
b.display()

Example output:

                              __50_________________________________________ 
                             /                                             \
    ________________________43_                   ________________________99
   /                           \                 /                          
  _9_                         48    ____________67_____________________     
 /   \                             /                                   \    
 3  11_________                   54___                         ______96_   
/ \            \                       \                       /         \  
0 8       ____26___________           61___           ________88___     97  
         /                 \         /     \         /             \        
        14_             __42        56    64_       75_____       92_       
       /   \           /                 /   \     /       \     /   \      
      13  16_         33_               63  65_   72      81_   90  94      
             \       /   \                     \         /   \              
            25    __31  41                    66        80  87              
                 /                                     /                    
                28_                                   76                    
                   \                                                        
                  29                                                        

答案 1 :(得分:8)

这有一个家庭作业的声音,如果是,你应该提到它。但是,这仍然是一个合理的问题。

您正在寻找的是breadth-first traversal,它允许您逐级遍历树级。基本上,您使用队列来跟踪您需要访问的节点,将子节点添加到队列的 back (而不是将它们添加到前面堆栈)。让它先工作。

执行此操作后,您可以确定树有多少级别(log2(node_count) + 1)并使用它来估计空格。如果要完全正确地获取空白,可以使用其他数据结构来跟踪每个级别需要多少空格。但是,使用节点数和级别的智能估计应该足够了。

答案 2 :(得分:5)

我将在这里留下@J 的独立版本。 V. 的代码。如果有人想获取他/她自己的二叉树并漂亮地打印它,请传递根节点,您就可以开始了。

如有必要,请根据您的节点定义更改 valleftright 参数。

def print_tree(root, val="val", left="left", right="right"):
    def display(root, val=val, left=left, right=right):
        """Returns list of strings, width, height, and horizontal coordinate of the root."""
        # No child.
        if getattr(root, right) is None and getattr(root, left) is None:
            line = '%s' % getattr(root, val)
            width = len(line)
            height = 1
            middle = width // 2
            return [line], width, height, middle

        # Only left child.
        if getattr(root, right) is None:
            lines, n, p, x = display(getattr(root, left))
            s = '%s' % getattr(root, val)
            u = len(s)
            first_line = (x + 1) * ' ' + (n - x - 1) * '_' + s
            second_line = x * ' ' + '/' + (n - x - 1 + u) * ' '
            shifted_lines = [line + u * ' ' for line in lines]
            return [first_line, second_line] + shifted_lines, n + u, p + 2, n + u // 2

        # Only right child.
        if getattr(root, left) is None:
            lines, n, p, x = display(getattr(root, right))
            s = '%s' % getattr(root, val)
            u = len(s)
            first_line = s + x * '_' + (n - x) * ' '
            second_line = (u + x) * ' ' + '\\' + (n - x - 1) * ' '
            shifted_lines = [u * ' ' + line for line in lines]
            return [first_line, second_line] + shifted_lines, n + u, p + 2, u // 2

        # Two children.
        left, n, p, x = display(getattr(root, left))
        right, m, q, y = display(getattr(root, right))
        s = '%s' % getattr(root, val)
        u = len(s)
        first_line = (x + 1) * ' ' + (n - x - 1) * '_' + s + y * '_' + (m - y) * ' '
        second_line = x * ' ' + '/' + (n - x - 1 + u + y) * ' ' + '\\' + (m - y - 1) * ' '
        if p < q:
            left += [n * ' '] * (q - p)
        elif q < p:
            right += [m * ' '] * (p - q)
        zipped_lines = zip(left, right)
        lines = [first_line, second_line] + [a + u * ' ' + b for a, b in zipped_lines]
        return lines, n + m + u, max(p, q) + 2, n + u // 2

    lines, *_ = display(root, val, left, right)
    for line in lines:
        print(line)

print_tree(root)

          __7 
         /   \
     ___10_  3
    /      \  
  _19     13  
 /   \        
 9   8_       
/ \    \      
4 0   12 

答案 3 :(得分:3)

class Node(object):
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right
    
def printTree(node, level=0):
    if node != None:
        printTree(node.left, level + 1)
        print(' ' * 4 * level + '->', node.value)
        printTree(node.right, level + 1)

t = Node(1, Node(2, Node(4, Node(7)),Node(9)), Node(3, Node(5), Node(6)))
printTree(t)

输出:

            -> 7
        -> 4
    -> 2
        -> 9
-> 1
        -> 5
    -> 3
        -> 6

答案 4 :(得分:2)

我增强了Prashant Shukla answer以在同一行中打印同一行上没有空格的节点。

class Node(object):
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

    def __str__(self):
        return str(self.value)


def traverse(root):
    current_level = [root]
    while current_level:
        print(' '.join(str(node) for node in current_level))
        next_level = list()
        for n in current_level:
            if n.left:
                next_level.append(n.left)
            if n.right:
                next_level.append(n.right)
            current_level = next_level

t = Node(1, Node(2, Node(4, Node(7)), Node(9)), Node(3, Node(5), Node(6)))

traverse(t)

答案 5 :(得分:1)

正在通过here回答类似问题这可能有助于以下代码以此格式打印

>>> 
1
2 3
4 5 6
7
>>> 

此代码如下:

class Node(object):
  def __init__(self, value, left=None, right=None):
   self.value = value
   self.left = left
   self.right = right

def traverse(rootnode):
  thislevel = [rootnode]
  a = '                                 '
  while thislevel:
    nextlevel = list()
    a = a[:len(a)/2]
    for n in thislevel:
      print a+str(n.value),
      if n.left: nextlevel.append(n.left)
      if n.right: nextlevel.append(n.right)
      print
      thislevel = nextlevel

t = Node(1, Node(2, Node(4, Node(7)),Node(9)), Node(3, Node(5), Node(6)))

traverse(t)

已编辑的代码以此格式显示结果:

>>> 
              1
      2         3
  4     9     5     6
7
>>> 

这只是一种方法,可以做你想要的正确方法,我建议你多挖一点。

答案 6 :(得分:0)

class magictree:
    def __init__(self, parent=None):
        self.parent = parent
        self.level = 0 if parent is None else parent.level + 1
        self.attr = []
        self.rows = []

    def add(self, value):
        tr = magictree(self)
        tr.attr.append(value)
        self.rows.append(tr)
        return tr

    def printtree(self):
        def printrows(rows):
            for i in rows:
                print("{}{}".format(i.level * "\t", i.attr))
                printrows(i.rows)

        printrows(self.rows)

tree = magictree()
group = tree.add("company_1")
group.add("emp_1")
group.add("emp_2")
emp_3 = group.add("emp_3")

group = tree.add("company_2")
group.add("emp_5")
group.add("emp_6")
group.add("emp_7")

emp_3.add("pencil")
emp_3.add("pan")
emp_3.add("scotch")

tree.printtree()

结果:

['company_1']
    ['emp_1']
    ['emp_2']
    ['emp_3']
        ['pencil']
        ['pan']
        ['scotch']
['company_2']
    ['emp_5']
    ['emp_6']
    ['emp_7']

答案 7 :(得分:0)

当我从 Google 提出这个问题时(我敢打赌,很多其他人也这样做了),这里是有多个子节点的二叉树,带有打印函数(__str__,它在执行 str(object_var)print(object_var))。

代码:

from typing import Union, Any

class Node:
    def __init__(self, data: Any):
        self.data: Any = data
        self.children: list = []
    
    def insert(self, data: Any):
        self.children.append(Node(data))

    def __str__(self, top: bool=True) -> str:
        lines: list = []
        lines.append(str(self.data))
        for child in self.children:
            for index, data in enumerate(child.__str__(top=False).split("\n")):
                data = str(data)
                space_after_line = "   " * index
                if len(lines)-1 > index:
                    lines[index+1] += "   " + data
                    if top:
                        lines[index+1] += space_after_line
                else:
                    if top:
                        lines.append(data + space_after_line)
                    else:
                        lines.append(data)
                for line_number in range(1, len(lines) - 1):
                    if len(lines[line_number + 1]) > len(lines[line_number]):
                        lines[line_number] += " " * (len(lines[line_number + 1]) - len(lines[line_number]))

        lines[0] = " " * int((len(max(lines, key=len)) - len(str(self.data))) / 2) + lines[0]
        return '\n'.join(lines)

    def hasChildren(self) -> bool:
        return bool(self.children)

    def __getitem__(self, pos: Union[int, slice]):
        return self.children[pos]

然后是一个演示:

# Demo
root = Node("Languages Good For")
root.insert("Serverside Web Development")
root.insert("Clientside Web Development")
root.insert("For Speed")
root.insert("Game Development")
root[0].insert("Python")
root[0].insert("NodeJS")
root[0].insert("Ruby")
root[0].insert("PHP")
root[1].insert("CSS + HTML + Javascript")
root[1].insert("Typescript")
root[1].insert("SASS")
root[2].insert("C")
root[2].insert("C++")
root[2].insert("Java")
root[2].insert("C#")
root[3].insert("C#")
root[3].insert("C++")
root[0][0].insert("Flask")
root[0][0].insert("Django")
root[0][1].insert("Express")
root[0][2].insert("Ruby on Rails")
root[0][0][0].insert(1.1)
root[0][0][0].insert(2.1)
print(root)