基於二叉堆的二叉樹繪制方法
注:本文所述方法中的二叉樹以鏈表的形式存儲。
1 繪圖前准備。
首先你的二叉樹要以鏈表的形式存儲,你的節點類中方法的命名要如下所示:
class BinaryTree:
def __init__(self,value):
self.value=value
self.left=None
self.right=None
self.indexInHeap=None
def getIndexHeap(self):
return self.indexInHeap
def setIndexHeap(self,value):
self.indexInHeap=value
def insertLeft(self,newNode):
if self.left==None:
self.left=BinaryTree(newNode)
else:
t=BinaryTree(newNode)
t.left=self.left
self.left=t
def insertRight(self,newNode):
if self.right==None:
self.right=BinaryTree(newNode)
else:
t=BinaryTree(newNode)
t.right=self.right
self.right=t
def getValue(self):
return self.value
def setValue(self,value):
self.value=value
def getRightChild(self):
return self.right
def getLeftChild(self):
return self.left
2、繪圖的基本思想
首先通過二叉樹的高度,得出最底層滿二叉樹的葉子節點樹,隨后將該樹滿二叉樹的葉節點求出,然后層層向上遞推,求出所有節點的坐標,然后存為二叉堆數組。同時將你的二叉樹存為二叉堆數組,二者一一對應,通過mathplo的annotate進行繪制。
注:有人回復的時候我再介紹詳細的思想;
所有涉及的函數以及簡單示例如下:
import matplotlib.pyplot as plt
from treeClass import myOwnTree
def getNumberOfLeafs(tree):
leafNumber = 0##對應none節點
if tree:
if not tree.getRightChild() and not tree.getLeftChild():
leafNumber+=1
else:
leafNumber+=getNumberOfLeafs(tree.getLeftChild())
leafNumber += getNumberOfLeafs(tree.getRightChild())
return leafNumber
def getDeepOfTree(tree):
maxDeep=0#不符合情況的那個是0
if tree:
maxLeft=getDeepOfTree(tree.getLeftChild())
maxRight=getDeepOfTree(tree.getRightChild())
if maxLeft>maxRight:
maxDeep=maxLeft
return 1+maxLeft
else:
maxDeep=maxRight
return 1+maxRight
return maxDeep
def printTreePre(tree):
if tree:
print(tree.getValue())
printTreePre(tree.getLeftChild())
printTreePre(tree.getRightChild())
# tree(treeLen-4)
def getDuiIndex(tree):
if tree:
if tree.getLeftChild():
tree.getLeftChild().setIndexHeap(2*tree.getIndexHeap())
if tree.getRightChild():
tree.getRightChild().setIndexHeap(2 * tree.getIndexHeap()+1)
getDuiIndex(tree.getLeftChild())
getDuiIndex(tree.getRightChild())
def getDuiHelp(list,tree):
if tree:
list[tree.getIndexHeap()]=tree.getValue()
getDuiHelp(list,tree.getLeftChild())
getDuiHelp(list,tree.getRightChild())
return list
def getDuiList(tree):
getDuiIndex(tree)#給每個節點添加堆序號
h=getDeepOfTree(tree)
res=[None for i in range(2**h-1)]
res.insert(0,0)
return getDuiHelp(res,tree)
def drawBinaryTree(r,nodeType=dict(boxstyle="round", fc=(1.0, 0.7, 0.7), ec="none")):
# 接下來用我的方式畫這個圖
fig = plt.figure(1, facecolor="white")
fig.clf()
ax1 = plt.subplot(111, frameon=False)
h = getDeepOfTree(r)
if h==1:#如果只有一層
ax1.annotate(r.getValue(), va="center", ha="center", xy=(0.5,0.5), bbox=nodeType) ##畫出這個點
return None
w = getNumberOfLeafs(r)
detH = 1 / (h - 1)
yAxis = []
startY = 0
while startY <= 1:
yAxis.append(startY)
startY += detH
allLeafs = 2 ** (h - 1)
detX = 1 / (allLeafs - 1)
leafPos = []
startX = 0
while startX <= 1:
leafPos.append(startX)
startX += detX
allXList = []
while len(leafPos) >= 1:
allXList.append(leafPos)
tempList = []
i = 0
while i < len(leafPos) - 1:
tempList.append((leafPos[i] + leafPos[i + 1]) / 2)
i += 2
leafPos = tempList
allXList = allXList[::-1]
finPos = []
for xList, y in zip(allXList, yAxis[::-1]):
for item in xList:
finPos.append([item, y])
finPos.insert(0, 0) # 為了使下標滿足左右子樹之間的關系,這里在開始的位置添加占位符
##接下來將二叉樹存為二叉堆的形式
r.setIndexHeap(1)
duiListForR = getDuiList(r)
##開始畫
for i in range(1, len(duiListForR)):
if duiListForR[i]:
##然后畫出這個點指出去的箭頭
if 2*i
ax1.annotate("", xy=(finPos[i][0], finPos[i][1]),xytext=(finPos[2*i][0],finPos[2*i][1]),va="center", ha="center",bbox=nodeType,arrowprops=dict(arrowstyle="<-"))##畫出這個點
if 2*i+1鄭州哪個醫院做人流好 http://www.hnmt120.com/
ax1.annotate("", xy=(finPos[i][0], finPos[i][1]),xytext=(finPos[2*i+1][0],finPos[2*i+1][1]),va="center", ha="center",bbox=nodeType,arrowprops=dict(arrowstyle="<-"))##畫出這個點
for i in range(1, len(duiListForR)):
if duiListForR[i]:
ax1.annotate(duiListForR[i],va="center", ha="center",xy= (finPos[i][0], finPos[i][1]),bbox=nodeType)##畫出這個點
if __name__ == '__main__':
r = myOwnTree.BinaryTree("a")
r.insertLeft("b")
r.insertRight("c")
r.getRightChild().insertLeft("d")
r.getRightChild().getLeftChild().insertRight("g")
r.getLeftChild().insertRight("f")
r.getLeftChild().insertLeft("h")
r.getLeftChild().getLeftChild().insertLeft("i")
r.getLeftChild().getLeftChild().insertRight("k")
r.getLeftChild().getLeftChild().getLeftChild().insertRight("l")
r.getLeftChild().getLeftChild().getLeftChild().insertLeft("m")
# ##生成一個圖片,圖片上進行注釋
# toothType=dict(boxstyle="sawtooth", fc="0.8")#波浪形
leafNod=dict(boxstyle="round", fc=(1.0, 0.7, 0.7), ec="none")#圓形
drawBinaryTree(r,leafNod)
繪制的效果如下圖所示:
3、如果你覺得上面寫的過於麻煩
如果你對繪制和二叉樹的操作過程不求甚解,只求應用的話,我的代碼已經上到了git上。
github上的代碼
下載下來之后將里面的兩個文件夾拷到你的項目里,然后就可以直接引用了:
#畫圖函數
import drawPicture.viewBinaryTree as binaryView
#導入二叉樹的構建類
from treeClass.myOwnTree import BinaryTree
##隨意構建樹
r = BinaryTree("a")
r.insertLeft("b")
r.insertRight("c")
r.getRightChild().insertLeft("d")
r.getRightChild().getLeftChild().insertRight("g")
r.getLeftChild().insertRight("f")
##畫出來
leafNod=dict(boxstyle="round", fc=(1.0, 0.7, 0.7), ec="none")
binaryView.drawBinaryTree(r,leafNod)
