数据结构 - 树的遍历方法举例

树的遍历

我们已经见到了树数据结构的基本功能,现在是看树的一些额外使用模式的时候了。这些使用模式可以分为我们访问树节点的三种方式。有三种常用的模式来访问树中的所有节点。这些模式之间的差异是每个节点被访问的顺序。我们称这种访问节点方式为“遍历”。我们将看到三种遍历方式称为前序,中序后序 。让我们更仔细地定义这三种遍历方式,然后看看这些模式有用的一些例子。

前序 在前序遍历中,我们首先访问根节点,然后递归地做左侧子树的前序遍历,随后是右侧子树的递归前序遍历。 中序 在一个中序遍历中,我们递归地对左子树进行一次遍历,访问根节点,最后递归遍历右子树。 后序 在后序遍历中,我们递归地对左子树和右子树进行后序遍历,然后访问根节点。

让我们看一些例子,来说明这三种遍历。首先看前序遍历。作为遍历的树的示例,我们将把这本书表示为树。这本书是树的根,每一章都是根节点的一个孩子。章节中的每个章节都是章节的子节点,每个小节都是章节的子节点,依此类推。下图展示了一本只有两章的书的有限版本。注意,遍历算法适用于具有任意数量子节点的树,但是我们现在使用二叉树。

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

猜你喜欢

转载自blog.csdn.net/jhlovetll/article/details/84679881