树的遍历
深度优先遍历
深度优先遍历分为前序遍历,中序遍历,后序遍历。顾名思义,三者的不同在于输出顺序不同。二叉树的遍历代码如下:
def preorder(tree, height=0):
if tree is None:
return
print(tree.get_label())
preorder(tree.get_left(), height + 1)
preorder(tree.get_right(), height + 1)
def inorder(tree, height=0):
if tree is None:
return
inorder(tree.get_left(), height + 1)
print(tree.get_label())
inorder(tree.get_right(), height + 1)
def postorder(tree, height=0):
if tree is None:
return
postorder(tree.get_left(), height + 1)
postorder(tree.get_right(), height + 1)
print(tree.get_label())
遍历顺序的判断方法:从根节点上方开始,沿着所有节点外侧勾勒出树的轮廓,最后回到根节点上方。当经过节点的左方时记录节点的标签为前序遍历;当经过节点的下方时记录节点的标签为中序遍历;当经过节点的右方时记录节点的标签为后序遍历。值得注意的是,中序遍历的输出结果为顺序结果。
层序遍历
顾名思义,逐层遍历。较为简单,通常用迭代进行遍历即可。
树的剪枝
当对树的节点进行查询时,使用遍历效率太低,此时需要对树进行剪枝,例:输出二叉树两节点之间的路径。
class BST(object):
def __init__(self, key, left=None, right=None, parent=None, level=0):
self.__label = key
self.__left = left
self.__right = right
self.__parent = parent
self.__level = level
def add(self, key, lv=0):
if key == self.__label:
return
if key > self.__label:
if self.__right is None:
self.__right = BST(key, parent=self, level=lv + 1)
else:
self.__right.add(key, lv + 1)
if key < self.__label:
if self.__left is None:
self.__left = BST(key, parent=self, level=lv + 1)
else:
self.__left.add(key, lv + 1)
def find(self, key):
if self is None:
return None
if self.__label < key:
return self.__right.find(key)
elif self.__label > key:
return self.__left.find(key)
else:
return self
def get_left(self):
return self.__left
def get_right(self):
return self.__right
def get_label(self):
return self.__label
def get_parent(self):
return self.__parent
def get_level(self):
return self.__level
def find_path(tree, key1, key2):
tree1 = tree.find(key1)
tree2 = tree.find(key2)
path1 = []
path2 = []
while tree1.get_label() != tree2.get_label():
if tree1.get_level() > tree2.get_level():
path1.append(tree1.get_label())
tree1 = tree1.get_parent()
elif tree1.get_level() < tree2.get_level():
path2.insert(0, tree2.get_label())
tree2 = tree2.get_parent()
elif tree1.get_level() == tree2.get_level():
path1.append(tree1.get_label())
path2.insert(0, tree2.get_label())
tree1 = tree1.get_parent()
tree2 = tree2.get_parent()
path1.append(tree1.get_label())
path = path1 + path2
path = [str(node) for node in path]
print('->'.join(path))
numbers = [30, 40, 50, 35, 20, 10, 60, 55, 70, 25]
a, b = 35, 55
bst = BST(numbers[0])
for number in numbers[1:]:
bst.add(number)
find_path(bst, a, b)
实际上,二叉搜索是一维搜索。更进一步的,可以通过增加树的分叉数量达到增加搜索维度的目的。如二维搜索(平面搜索)则应通过四叉树进行搜索,四个分叉分别表示节点位于西北,东北,西南,东南象限。代码与二叉搜索类似,不再赘述。