1. 程式人生 > >二叉樹的各種演算法(一)python

二叉樹的各種演算法(一)python

即將進入秋招,樓主後續會複習一些資料結構演算法題目python版本+機器學習主流演算法的原理及推導,有空更。

今天是關於二叉樹元素新增(佇列實現),前序、中序、後序遍歷的遞迴與棧實現,最大深度與最大距離的遞迴實現

PS:樓主大致就用了一個例子測試了下,暫時沒有毛病,若有bug私信或評論我修改,如有雷同,就當我是抄你的,若還是有版權糾紛私信我,你們是大佬我是小弟,向大佬低頭(其實這些演算法不可能完全是我憑空想出來的,肯定是我以前見到過這些思路,此次回憶實現而已)。

  • 首先定義節點class和二叉樹class,這裡樹初始為空節點
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" Created on Mon Jul 31 23:06:50 2017 @author: xuhy """ class Node():#節點class,初始值為None def __init__(self,value=None,lchild=None,rchild=None): self.value=value self.lchild=lchild self.rchild=rchild class BTree():#BTree二叉樹class def __init__(self,root=Node()):#初始化預設root為一個Node()
self.root=root
  • 然後是層次新增元素,用了一個佇列
    def add(self,new):#二叉樹層次新增
        #利用一個佇列,以根節點開始,如果這一層沒有空位,則全部入佇列
        #依次檢查下一層,如果有空位則直接填補空位,若沒有則節點入佇列
        if self.root.value==None:
            self.root=Node(new)
        else:
            stack=[]
            stack.append(self.root)
            while
stack: node=stack.pop(0)#因為是佇列,所以是pop(0) if node.lchild==None: node.lchild=Node(new) return elif node.rchild==None: node.rchild=Node(new) return else: stack.append(node.lchild) stack.append(node.rchild)
  • 接下來是前序、中序、後序的遞迴實現
    #前序遍歷遞迴
    def front_digui(self,root):
        #這裡解釋下or,or左邊表示葉子節點子節點,or右邊表示空樹
        if root==None or root.value==None:
            return
        else:
            print(root.value)
            self.front_digui(root.lchild)
            self.front_digui(root.rchild)

    #中序遞迴
    def mid_digui(self,root):
        if root==None or root.value==None:
            return
        else:
            self.mid_digui(root.lchild)
            print(root.value)
            self.mid_digui(root.rchild)

    #後序遞迴
    def back_digui(self,root):
        if root==None or root.value==None:
            return
        else:
            self.back_digui(root.lchild)
            self.back_digui(root.rchild)   
            print(root.value)
  • 然後是三種遍歷的棧實現,個人覺得後序有點厲害
    #前序遍歷,一個棧stack一個指示節點node
    #總的思路就是,一路走到黑先把左邊走到底,順便print+入棧,
    #然後依次從棧裡取節點,指示node更正,繼續上述操作
    def front_stack(self,root):
        if root.value==None:
            return
        node=root
        stack=[]
        while node or stack:
            while node:
                stack.append(node)
                print(node.value)
                node=node.lchild
            node=stack.pop()
            node=node.rchild
    #中序遍歷,一個棧stack一個指示節點node
    #總的思路為,一路走到左邊黑,順便入棧
    #然後依次出棧,print+指示node更正,繼續上述操作      
    def mid_stack(self,root):
        if root.value==None:
            return
        node=root
        stack=[]
        while node or stack:
            while node:
                stack.append(node)
                node=node.lchild
            node=stack.pop()
            print(node.value)
            node=node.rchild

    #後續遍歷,兩個棧stack一個指示節點node
    #個人認為最難,因為根節點最後輸出,直接看程式碼吧
    def back_stack(self,root):
        if root.value==None:
            return
        node=root
        stack1=[]
        stack2=[]
        stack1.append(node)
        while stack1:
            node=stack1.pop()
            stack2.append(node)
            if node.lchild:
                stack1.append(node.lchild)
            if node.rchild:
                stack1.append(node.rchild)
        while stack2:
            node=stack2.pop()
            print(node.value)
  • 接著是遞迴求二叉樹的最大深度與距離,其中最大距離好像是《程式設計之美》上面的一道題目,這裡連同最大深度一起輸出,如果理解上有困難,讀者可以拿出筆和紙畫一畫,理一理。
    #同時計算二叉樹最大深度和距離,利用遞迴思想recur
    #思路就是,樹的最大深度為左子樹或右子樹的最大深度+1;
    #最大距離就是,樹的最大距離要麼是左子樹最大距離,要麼是右子樹最大距離
    #再要麼是左子樹最大深度+右子樹最大深度+1+1,三者取最大值;
    #這裡認為單節點樹深度為0,距離為0
    def get_depth_dis(self,root):
        if root.value==None:
            return
        elif root.lchild==None and root.rchild==None:
            return 0,0
        elif root.lchild==None and root.rchild!=None:
            return (self.get_depth_dis(root.rchild)[0]+1,
                    max(self.get_depth_dis(root.rchild)[1],
                        self.get_depth_dis(root.rchild)[0]+1))
        elif root.rchild==None and root.lchild!=None:
            return (self.get_depth_dis(root.lchild)[0]+1,
                    max(self.get_depth_dis(root.lchild)[1],
                        self.get_depth_dis(root.lchild)[0]+1))
        else:
            return (max(self.get_depth_dis(root.lchild)[0]+1,
                        self.get_depth_dis(root.rchild)[0]+1),
                    max(self.get_depth_dis(root.lchild)[1],
                        self.get_depth_dis(root.rchild)[1],
                        self.get_depth_dis(root.lchild)[0]+1+
                        self.get_depth_dis(root.rchild)[0]+1))

這次先到這裡,實習的事兒也得做,就偶爾抽點時間練下手。
下次應該是層次遍歷、中序+其他序重構二叉樹、二叉樹映象。。。
see you!
pps:有空還想試驗下GAN的幾個版本,如果做了也會更新,不知道我的1060受得了不,天殺的黃牛&曠工,還我1080ti!
哎,暑假完又要回實驗室搬磚啦,畢竟不能坑老闆呀,恩我是電氣工程的。。。