树结构(二)

树的遍历

深度优先遍历

  深度优先遍历分为前序遍历,中序遍历,后序遍历。顾名思义,三者的不同在于输出顺序不同。二叉树的遍历代码如下:

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)

  实际上,二叉搜索是一维搜索。更进一步的,可以通过增加树的分叉数量达到增加搜索维度的目的。如二维搜索(平面搜索)则应通过四叉树进行搜索,四个分叉分别表示节点位于西北,东北,西南,东南象限。代码与二叉搜索类似,不再赘述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值