二叉樹及其遍歷方法---python實現


github:代碼實現
本文算法均使用python3實現


1. 二叉樹

1.1 二叉樹的定義

  二叉樹是一種特殊的樹,它具有以下特點
  (1)樹中每個節點最多只能有兩棵樹,即每個節點的度最多為2。
  (2)二叉樹的子樹有左右之分,即左子樹右子樹,次序不能顛倒。
  (3)二叉樹即使只有一個子樹時,也要區分是左子樹還是右子樹。

1.2 滿二叉樹

  滿二叉樹作為一種特殊的二叉樹,它是指:所有的分支節點都存在左子樹與右子樹,並且所有的葉子節點都在同一層上。其特點有:
  (1)葉子節點只能出現在最下面一層
  (2)非葉子節點度一定是2
  (3)在同樣深度的二叉樹中,滿二叉樹的節點個數最多,節點個數為: $ 2^h -1 $ ,其中 $ h $ 為樹的深度。

1.3 完全二叉樹

  若設二叉樹的深度為 $ h $ ,除第 $ h $ 層外,其它各層 $ (1~h-1) $ 的結點數都達到最大個數,第 $ h $ 層所有的結點都連續集中在最左邊,這就是完全二叉樹。其具有以下特點
  (1)葉子節點可以出現在最后一層或倒數第二層。
  (2)最后一層的葉子節點一定集中在左部連續位置。
  (3)完全二叉樹嚴格按層序編號。(可利用數組或列表進行實現,滿二叉樹同)
  (4)若一個節點為葉子節點,那么編號比其大的節點均為葉子節點。


2. 二叉樹的相關性質

2.1 二叉樹性質

  (1)在非空二叉樹的 $ i $ 層上,至多有 $ 2^{i-1} $ 個節點 $ (i \geq 1) $ 。
  (2)在深度為 $ h $ 的二叉樹上最多有 $ 2^h -1 $ 個節點 $(k \geq 1) $ 。
  (3)對於任何一棵非空的二叉樹,如果葉節點個數為 $ n_0 $ ,度數為 $ 2 $ 的節點個數為 $ n_2 $ ,則有: $ n_0 = n_2 + 1 $ 。

2.1 完全二叉樹性質

  (1)具有 $ n $ 個的結點的完全二叉樹的深度為 $ \log_2{n+1} $ 。.
  (2)如果有一顆有 $ n $ 個節點的完全二叉樹的節點按層次序編號,對任一層的節點 $ i ,(1 \geq i \geq n)$ 有:
    (2.1)如果 $ i=1 $ ,則節點是二叉樹的根,無雙親,如果 $ i>1 $ ,則其雙親節點為 $ \lfloor i/2 \rfloor $ 。
    (2.2)如果 $ 2i>n $ 那么節點i沒有左孩子,否則其左孩子為 $ 2i $ 。
    (2.3)如果 $ 2i+1>n $ 那么節點沒有右孩子,否則右孩子為 $ 2i+1 $ 。


3. 二叉樹的遍歷

  以下遍歷以該二叉樹為例:

3.1 前序遍歷

  思想:先訪問根節點,再先序遍歷左子樹,然后再先序遍歷右子樹。總的來說是根—左—右
  上圖先序遍歷結果為為:$ 1,2,4,8,9,5,3,6,7 $
  代碼如下:

	def PreOrder(self, root):
		'''打印二叉樹(先序)'''
		if root == None:
			return 
		print(root.val, end=' ')
		self.PreOrder(root.left)
		self.PreOrder(root.right)

3.2 中序遍歷

  思想:先中序訪問左子樹,然后訪問根,最后中序訪問右子樹。總的來說是左—根—右
  上圖中序遍歷結果為為:$ 8,4,9,2,5,1,6,3,7 $
  代碼如下:

	def InOrder(self, root):
		'''中序打印'''
		if root == None:
			return
		self.InOrder(root.left)
		print(root.val, end=' ')
		self.InOrder(root.right)

3.3 后序遍歷

  思想:先后序訪問左子樹,然后后序訪問右子樹,最后訪問根。總的來說是左—右—根
  上圖后序遍歷結果為為:$ 8,9,4,5,2,6,7,3,1 $
  代碼如下:

	def BacOrder(self, root):
		'''后序打印'''
		if root == None:
			return
		self.BacOrder(root.left)
		self.BacOrder(root.right)
		print(root.val, end=' ')

3.4 層次遍歷(寬度優先遍歷)

  思想:利用隊列,依次將根,左子樹,右子樹存入隊列,按照隊列先進先出規則來實現層次遍歷。
  上圖后序遍歷結果為為:$ 1,2,3,4,5,6,7,8,9 $
  代碼如下:

	def BFS(self, root):
		'''廣度優先'''
		if root == None:
			return
		# queue隊列,保存節點
		queue = []
		# res保存節點值,作為結果
		#vals = []
		queue.append(root)

		while queue:
			# 拿出隊首節點
			currentNode = queue.pop(0)
			#vals.append(currentNode.val)
			print(currentNode.val, end=' ')
			if currentNode.left:
				queue.append(currentNode.left)
			if currentNode.right:
				queue.append(currentNode.right)
		#return vals

3.5 深度優先遍歷

  思想:利用,先將根入棧,再將根出棧,並將根的右子樹,左子樹存入棧,按照先進后出規則來實現深度優先遍歷。
  上圖后序遍歷結果為為:$ 1,2,4,8,9,5,3,6,7 $
  代碼如下:

	def DFS(self, root):
		'''深度優先'''
		if root == None:
			return
		# 棧用來保存未訪問節點
		stack = []
		# vals保存節點值,作為結果
		#vals = []
		stack.append(root)

		while stack:
			# 拿出棧頂節點
			currentNode = stack.pop()
			#vals.append(currentNode.val)
			print(currentNode.val, end=' ')
			if currentNode.right:
				stack.append(currentNode.right)
			if currentNode.left:
				stack.append(currentNode.left)			
		#return vals

3.6 代碼運行結果


引用及參考:
[1]《數據結構》李春葆著
[2] http://www.cnblogs.com/polly333/p/4740355.html

寫在最后:本文參考以上資料進行整合與總結,屬於原創,文章中可能出現理解不當的地方,若有所見解或異議可在下方評論,謝謝!
若需轉載請注明https://www.cnblogs.com/lliuye/p/9143676.html


免責聲明!

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



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