# CY3761 | 2021-12-22 11:15

"""

A
BC(A)
DE(B) FG(C)
H(D)

树的深度优先遍历
先序遍历
根节点->左子树->右子树

从根开始
是否具有子树?是
遍历左节点.. 接着循环
是否具有子树,无
往上一层,是否具有右子树?是
遍历右节点.. 接着循环
假设如果E有子节点,则继续下层遍历左再往上遍历右

A->B->D->H->E->C->F->G

中序遍历
左子树->右子树->根节点

从左节点(最深处)
往上进行
往上进行判断同时自己也是左的情况下,找是否具有右子树,有则遍历
右遍历后继续往上,到根
从右边点(最深处),遍历
往上进行,遍历
找是否具有右子树,有则遍历, 主要是左边到根已遍历完

H->D->B->A->E->F->C->G

后序遍历
左子树->右子树->根节点
H->D->E->B->F->G->C->A

"""

"""
0
12(0)
34(1) 56(2)
78(3) 9(4)

先序遍历
根节点->左子树->右子树

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

中序遍历
左子树->右子树->根节点

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

后序遍历
左子树->右子树->根节点
7->8->3->9->4->1->5->6->2->0

"""


# 节点类
class Node:
    def __init__(self, item):
        self.item = item  # 节点值
        self.lPoi = None  # 左指针域
        self.rPoi = None  # 右指针域


class Tree:
    def __init__(self):
        self.root = None  # 根节点
    
    def add(self, item):
        """
        添加节点 往树添加一个节点 并保证添加后的树是一个完全二叉树
        从上往下 从左往右 遍历树 找到树的空位
        把节点添加进去
        :param item: 添加节点的值
        :return:
        """
        
        # print('-' * 80)
        
        oNode = Node(item)  # 创建节点
        
        if not self.root:  # 判断 root 是否为空
            # print(item)
            self.root = oNode
            return
        
        items = [self.root]  # 每一层的节点进行存储
        
        while True:
            aItem = items.pop(0)  # 弹出第一个
            
            # print(item, getId(aItem), aItem.item, not aItem.lPoi, not aItem.rPoi)
            
            if not aItem.lPoi:  # 先找左边是否为空
                aItem.lPoi = oNode
                return
            
            elif not aItem.rPoi:  # 再找右边是否为空
                aItem.rPoi = oNode
                return
            
            # 如果左右都非空 则 加入数据
            items.extend((aItem.lPoi, aItem.rPoi))  # pop 从后面弹出
    
    def show(self):
        if not self.root:  # 判断 root 是否为空
            return
        
        items = [self.root]  # 每一层的节点进行存储
        
        while items:
            for _ in range(len(items)):
                node = items.pop(0)
                
                print(node.item, end='\t')
                
                if node.lPoi:  # 左边是否为空
                    items.append(node.lPoi)
                if node.rPoi:  # 右边是否为空
                    items.append(node.rPoi)
            print()
    
    # 先序遍历
    # 根节点->左子树->右子树
    def before(self):
        print('先序遍历:')
        
        def helper(root):  # 用于递归处理的
            if not root:
                return
            
            print(('' if root is self.root else '-> ') + str(root.item), end=' ')  # 输出根节点
            helper(root.lPoi)  # 左子树
            helper(root.rPoi)  # 右子树
        
        helper(self.root)
    
    # 中序遍历
    # 左子树->右子树->根节点
    def middle(self):
        print('\n中序遍历:')
        
        i = 0
        
        def helper(root, P):  # 用于递归处理的
            if not root:
                return
            
            P += 1
            print('(%d)' % P, end=' ')
            
            helper(root.lPoi, P)  # 左子树
            print(str(root.item), end=' ')  # 输出根节点
            helper(root.rPoi, P)  # 右子树
        
        helper(self.root, i)
    
    # 后序遍历
    # 左子树->右子树->根节点
    def after(self):
        print('\n后序遍历:')
        i = 0
        
        def helper(root, P):  # 用于递归处理的
            if not root:
                return
            
            P += 1
            print('(%d)' % P, end=' ')
            
            helper(root.lPoi, P)  # 左子树
            helper(root.rPoi, P)  # 右子树
            print(str(root.item), end=' ')  # 输出根节点
        
        helper(self.root, i)


if __name__ == '__main__':
    oT = Tree()
    
    for _ in range(10):
        # print('-' * 80)
        oT.add(_)
    
    oT.before()
    oT.middle()
    oT.after()

树深度度优先Java 树深度优先遍历算法_深度优先