python基礎知識學習——二叉樹的繪制


  基於二叉堆的二叉樹繪制方法

  注:本文所述方法中的二叉樹以鏈表的形式存儲。

  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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM