二叉樹的各種演算法(一)python
阿新 • • 發佈:2019-02-13
即將進入秋招,樓主後續會複習一些資料結構演算法題目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!
哎,暑假完又要回實驗室搬磚啦,畢竟不能坑老闆呀,恩我是電氣工程的。。。