13.2 二叉树(binary tree)
二叉树(binary tree)是每一个结点至多含有两个子结点的树结构。其中,对于含有两个子结点的结点,左边的子结点称为左子结点(left child node),相应的右边的称为右子结点(right child node)。
13.2.1 二叉树的性质
二叉树可以以不同形式和大小存在,其取决于结点的数目以及结点的相连形式。
树的大小
二叉树的结点可以按层(level)来分类,根结点在0层,其子结点在1层,1层结点的子结点在2层,以此类推。在二叉树中,某个结点的深度(depth)等于其所在层数。二叉树的高度(height)就是该二叉树的最大层数。二叉树的宽度(width)就是二叉树含最多结点的层,其所含的结点数。二叉树的大小(size)就是二叉树所含的结点数。
一个大小为n的二叉树,其最大高度可以为n,即每一层只有一个结点,其最小高度为[log n] + 1,即处叶结点外,所有结点都含有两个子结点。
树结构
满二叉树(full binary tree):除叶结点外,其余结点均含两个子结点,即所有内结点均含有两个子结点。
完美二叉树(perfect binary tree):所有叶结点都在同一层的满二叉树。
完全二叉树(complete binary tree):前h-1层为完美二叉树,最后一层从左到右,有若干个相互之间无空隙的结点的树结构。
13.2.2 实现
其实现方式与链表类似。
#-*-coding: utf-8-*-
# 二叉树的结点
class _BinTreeNode(object):
def __init__(self, data):
self.data = data
self.left = None
self.right = None
13.2.3 树遍历
二叉树的遍历方式有四种:
前序遍历(preorder traversal)
在访问根结点之后,先访问左子树的结点,再访问右子树的结点。以此递归形式,来对整个二叉树进行遍历。
# 前序遍历
def preorderTrav(subtree):
if subtree is not None:
print subtree.data
preorderTrav(subtree.left)
preorderTrav(subtree.right)
前序遍历是先访问根结点,再对其子树进行遍历。
中序遍历(inorder traversal)
中序遍历是先访问左子树,再访问根结点,最后访问右子树。
# 中序遍历
def inorderTrav(subtree):
if subtree is not None:
inorderTrav(subtree.left)
print subtree.data
inorderTrav(subtree.right)
后序遍历(postorder traversal)
# 后序遍历
def postorderTrav(subtree):
if subtree is not None:
postorderTrav(subtree.left)
postorderTrav(subtree.right)
print subtree.data
以上三种遍历方式统称为深度优先遍历(depth-first traversal),因为这种遍历方式都是先遍历更深的结点。
# 宽度优先遍历
def breadthFirstTrav(bintree):
from llistqueue import Queue
q = Queue()
q.enqueue(bintree)
while not q.isEmpty():
node = q.dequeue()
print node.data
if node.left is not None:
q.enqueue(node.left)
if node.right is not None:
q.enqueue(node.right)