学习笔记-二叉树-先序、中序、后序、层次遍历的实现(Python)

本文介绍了使用Python实现二叉树的方法,包括递归和非递归方式的先序、中序、后序遍历及层次遍历等,并提供完整的代码示例。

一、二叉树类的Python实现及其函数:包括统计结点个数,用递归实现的先序遍历,非递归实现的先序遍历,以及非递归实现的后序遍历。

class StackUnderflow(ValueError):   
    pass  
  
class SStack():  
    def __init__(self):  
        self.elems = []  
          
    def is_empty(self):  
        return self.elems == []  
      
    def top(self): #取得栈里最后压入的元素,但不删除  
        if self.elems == []:  
            raise StackUnderflow('in SStack.top()')  
        return self.elems[-1]  
      
    def push(self, elem):  
        self.elems.append(elem)  
          
    def pop(self):  
        if self.elems == []:  
            raise StackUnderflow('in SStack.pop()')  
        return self.elems.pop()
  
class BinTNode:
    def __init__(self, dat, left = None, right = None):
        self.data = dat
        self.left = left
        self.right = right

#统计树中结点的个数
def count_BinTNodes(t): 
    if t is None:
        return 0
    else:
        return 1 + count_BinTNodes(t.left) + count_BinTNodes(t.right)
    
#假设结点中保存的是数值,求此时二叉树里的所有数值的和
def sum_BinTNodes(t): 
    if t is None:
        return 0
    else:
        return t.data + sum_BinTNodes(t.left) + sum_BinTNodes(t.right)
    
def proc(x):
    print(x, end = '')

#利用递归实现的先序遍历
def pre_order(t): 
    if t is None:
        return
    proc(t.data)
    pre_order(t.left)
    pre_order(t.right)
  
#利用非递归实现的先序遍历
def preorder_nonrec(t):
    s = SStack()
    while t is not None or not s.is_empty():
        while t is not None:
            proc(t.data)
            s.push(t.right) #右分支入栈
            t = t.left     #沿着左分支下行
        t = s.pop()       #遇到空树,回溯
    
#用带有括号的形式显示出树,^代表空
def print_BinTNodes(t): 
    if t is  None:
        print('^', end = '')
        return
    print('(' + str(t.data), end = '')
    print_BinTNodes(t.left)
    print_BinTNodes(t.right)
    print(')', end = '')
    
#用生成器实现非递归先序遍历;当需要遍历数据的时候,总应该想到迭代器
def preorder_elemnts(t):
    s = SStack()
    while t is not None or not s.is_empty():
        while t is not None:
            s.push(t.right) #右分支入栈
            yield t.data
            t = t.left
        t = s.pop()
    #非递归遍历算法的一个重要用途是作为实现迭代器的基础
        
#利用非递归实现的后序遍历
def postorder_elements(t):
    s = SStack()
    while t is not None or not s.is_empty():
        while t is not None: #下行循环,知道到达树的叶结点
            s.push(t) #将树压入栈中
            t = t.left if t.left is not None else t.right #如果左子结点不空就先访问左子结点,为空就访问右子结点
            
        t = s.pop() #将栈顶的子树弹出   
        proc(t.data)
        if not s.is_empty() and s.top().left == t: #如果栈不为空且当前的子树是现在栈顶的左子结点
            t = s.top().right       #就转到当前栈顶的右子结点
        else:
            t = None

if __name__=="__main__":
    t = BinTNode(1, BinTNode(2, BinTNode(4), BinTNode(5)), BinTNode(3, BinTNode(6), BinTNode(7)))
    t = BinTNode(1, BinTNode(2,BinTNode(5)), BinTNode(3))
    print(count_BinTNodes(t))
    print(sum_BinTNodes(t))
    preorder_nonrec(t)
    print(pre_order(t))
    print_BinTNodes(t)
    for i in preorder_elements(t):
        print(i)
    postorder_elements(t)

二、下面是不用自己构造的栈类所写的4种遍历的实现:

class BinTNode:
    def __init__(self, dat, left = None, right = None):
        self.data = dat
        self.left = left
        self.right = right


# 利用递归实现的先序遍历
def pre_order(t):
    if t == None:
        return
    print(t.data)
    pre_order(t.left)
    pre_order(t.right)


# 利用递归实现的中序遍历
def mid_order(t):
    if t == None:
        return
    mid_order(t.left)
    print(t.data)
    mid_order(t.right)


# 利用递归实现的后序遍历
def post_order(t):
    if t == None:
        return
    post_order(t.left)
    post_order(t.right)
    print(t.data)


# 利用非递归实现的先序遍历
def pre_order_nonrec(t):
    stack = []
    while t != None or stack != []:
        while t != None:
            print(t.data)
            stack.append(t.right)  # 右分支入栈
            t = t.left  # 沿着左分支下行
        t = stack.pop()  # 遇到空树,回溯


# 利用非递归实现的中序遍历
def mid_order_nonrec(t):
    stack = []
    while t != None or stack != []:  # 最开始时栈为空,但t不为空;t = t.right可能为空,栈不为空;当两者都为空时,说明已经全部遍历完成了
        while t != None:
            stack.append(t)
            t = t.left
        t = stack.pop()  # 将栈顶元素弹出
        print(t.data)
        t = t.right   # 将当前结点的右子结点赋给t,让其在while中继续压入栈内


# 利用非递归实现的后序遍历
def post_order_nonrec(t):
    stack = []
    while t != None or stack != []:
        while t != None:  # 下行循环,直到到达树的叶结点
            stack.append(t)  # 将树压入栈中
            t = t.left if t.left is not None else t.right  # 如果左子结点不空就先访问左子结点,为空就访问右子结点
        t = stack.pop()  # 将栈顶的子树弹出
        print(t.data)
        if stack != [] and stack[-1].left == t:  # 如果栈不为空且当前的子树是现在栈顶的左子结点
            t = stack[-1].right  # 就转到当前栈顶的右子结点
        else:
            t = None    #否则就直接置为None,从栈中弹出下一个元素

#层次遍历
def level_order(t):
     if t == None:
        return
     lst = []
     lst.append(t)
     while lst:
         current=lst.pop(0)
         print(current.data)
         if current.left!=None:
            lst.append(current.left)
         if current.right!=None:
            lst.append(current.right)

if __name__ == "__main__":
    t = BinTNode(1, BinTNode(2, BinTNode(4), BinTNode(5)), BinTNode(3, BinTNode(6), BinTNode(7)))
    # t = BinTNode(1, BinTNode(2, BinTNode(5)), BinTNode(3))
    pre_order(t)
    pre_order_nonrec(t)

    mid_order(t)
    mid_order_nonrec(t)

    post_order(t)
    post_order_nonrec(t)

    level_order(t)



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值