1. 程式人生 > >資料結構 - 樹的遍歷方法舉例

資料結構 - 樹的遍歷方法舉例

樹的遍歷

我們已經見到了樹資料結構的基本功能,現在是看樹的一些額外使用模式的時候了。這些使用模式可以分為我們訪問樹節點的三種方式。有三種常用的模式來訪問樹中的所有節點。這些模式之間的差異是每個節點被訪問的順序。我們稱這種訪問節點方式為“遍歷”。我們將看到三種遍歷方式稱為前序,中序後序 。讓我們更仔細地定義這三種遍歷方式,然後看看這些模式有用的一些例子。

前序 在前序遍歷中,我們首先訪問根節點,然後遞迴地做左側子樹的前序遍歷,隨後是右側子樹的遞迴前序遍歷。 中序 在一箇中序遍歷中,我們遞迴地對左子樹進行一次遍歷,訪問根節點,最後遞迴遍歷右子樹。 後序

 在後序遍歷中,我們遞迴地對左子樹和右子樹進行後序遍歷,然後訪問根節點。

讓我們看一些例子,來說明這三種遍歷。首先看前序遍歷。作為遍歷的樹的示例,我們將把這本書表示為樹。這本書是樹的根,每一章都是根節點的一個孩子。章節中的每個章節都是章節的子節點,每個小節都是章節的子節點,依此類推。下圖展示了一本只有兩章的書的有限版本。注意,遍歷演算法適用於具有任意數量子節點的樹,但是我們現在使用二叉樹。

6.7.樹的遍歷.figure5

假設你想從前到後讀這本書。前序遍歷給你正確的順序。從樹的根(Book節點)開始,我們將遵循前序遍歷指令。我們遞迴呼叫左孩子的 preorder,在這種情況下是 Chapter1

。我們再次遞迴呼叫左孩子的 preorder 來得到 Section 1.1 。由於 Section 1.1沒有子節點,我們不再進行任何額外的遞迴呼叫。當我們完成 Section 1.1,我們將樹向上移動到Chapter1。此時,我們仍然需要訪問 Chapter1 的右子樹 Section 1.2。和前面一樣,我們訪問左子樹,它將我們帶到 Section 1.2.1,然後訪問 Section 1.2.2。在 Section 1.2 完成後,我們返回到 Chapter1
。然後,我們返回到 Book 節點,並按照相同過程遍歷 Chapter2

編寫樹遍歷的程式碼驚人地優雅,主要是因為遍歷是遞迴寫的。下面的程式碼展示了用於二叉樹的前序遍歷的 Python 程式碼。

你可能想知道,編寫像前序遍歷演算法的最好方法是什麼?是一個簡單地使用樹作為資料結構的函式,還是樹資料結構本身的方法?下面的程式碼展示了作為外部函式編寫的前序遍歷的版本,它將二叉樹作為引數。外部函式特別優雅,因為我們的基本情況只是檢查樹是否存在。如果樹引數為 None,那麼函式返回而不採取任何操作。

前序遍歷:

   def preorder(self, root):
      if self.root is None:
         return
      print root.value
      self.preorder(root.left)
      self.preorder(root.right)

中序遍歷:

   def inorder(self, root):
      if self.root is None:
         return
      self.inorder(root.left)
      print root.value
      self.inorder(root.right)

後序遍歷:

   def postorder(self, root):
      if self.root is None:
         return
      self.postorder(root.left)
      self.postorder(root.right)
      print root.value

對於數的廣度搜索BFS,也叫層次遍歷, 實現的方法主要是用佇列實現,將每一個結點進行入隊操作,然後結點出隊的同時,結點的左子樹和右子樹進行入隊操作.實現如下:

   def bfs(self):
      if self.root is None:
         return
      queue = [self.root]
      while queue:
         current = queue.pop(0)
         if current.left is not None:
            queue.append(current.left)
         if current.right is not None:
            queue.append(current.right)

完整程式,如下:

class Node(object):
   def __init__(self, item):
      self.element = item
      self.left = None
      self.right = None

class Tree(object):
   def __init__(self):
      self.root = None
      self.left = None
      self.right = None

   def add(self, item):
      node = Node(item)
      if self.root is None:
         self.root = node
         return
      queue = [self.root]
      while len(queue) != 0:
         current = queue.pop(0)
         if current.left is None:
            current.left = node
            return
         else:
            queue.append(current.left)

         if current.right is None:
            current.right = node
            return
         else:
            queue.append(current.right)

   def bfs(self):
      if self.root is None:
         return
      queue = [self.root]
      while queue:
         current = queue.pop(0)
         if current.left is not None:
            queue.append(current.left)
         if current.right is not None:
            queue.append(current.right)

   def preorder(self, root):
      if self.root is None:
         return
      print root.value
      self.preorder(root.left)
      self.preorder(root.right)

   def inorder(self, root):
      if self.root is None:
         return
      self.inorder(root.left)
      print root.value
      self.inorder(root.right)

   def postorder(self, root):
      if self.root is None:
         return
      self.postorder(root.left)
      self.postorder(root.right)
      print root.value