Python实现线索化二叉树 Python实现线索化存储二叉树 Python线索化二叉树的遍历

概述

  • 先看如下的二叉树,中序遍历结果为:[8,3,10,1,14,6]

在这里插入图片描述
在这里插入图片描述

  • 线索二叉树 思路:
    在这里插入图片描述
  • 梳理过程:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

Python实现:线索化存储二叉树

class TreeNode(object):
    def __init__(self, val=-1):
        self.val = val
        self.left = None
        self.right = None
        # 新增类型指针
        # 规定:
        # 如果left_type==0 表示指向的是左子树,如果是1 则表示指向前驱结点
        # 如果right_type==0 表示指向的是右子树,如果是1 怎表示指向后继结点
        self.left_type = 0 # 注意这里必须写0,不能写空值
        self.right_type = 0


class ThreadedBinaryTree(object):
    def __init__(self):
        self.root = None
        # 在递归进行线索化,总是保留前一个结点
        self.pre = None  # 为实现线索化,需要创建给指向当前结点的前驱结点指针

    # 添加结点测试
    def add(self, val):
        node = TreeNode(val)
        if self.root is None:
            self.root = node
            return
        queue = [self.root]
        while queue:
            temp_node = queue.pop(0)
            if temp_node.left is None:
                temp_node.left = node
                return
            else:
                queue.append(temp_node.left)
            if temp_node.right is None:
                temp_node.right = node
                return
            else:
                queue.append(temp_node.right)

    # 中序遍历测试
    def in_order(self, node):
        if node is None:
            return
        self.in_order(node.left)
        print(node.val, end=' ')
        self.in_order(node.right)

    # 二叉树进行中序线索化的方法
    def threaded_node(self, node):  # node: 就是当前需要线索化的结点
        if node is None:
            return
        # 先线索化左子树
        self.threaded_node(node.left)
        
        # 线索化当前结点
        # 处理当前结点的前驱结点
        if node.left is None:  # 如果当前结点左子结点为空
            node.left = self.pre  # 让当前结点的左指针指向前驱结点
            node.left_type = 1  # 修改当前结点的左指针类型 为 前驱结点
        # 处理当前结点的后继结点
        if self.pre and self.pre.right is None: 
            self.pre.right = node  # 让前驱结点的右指针指向当前结点
            self.pre.right_type = 1  # 修改前驱结点的右指针类型
        self.pre = node  # 每处理一个结点后,让当前结点是下一个结点的前驱结点
        
        # 线索化右子树
        self.threaded_node(node.right)


if __name__ == '__main__':
    t = ThreadedBinaryTree()
    # t.add(1)
    # t.add(3)
    # t.add(6)
    # t.add(8)
    # t.add(10)
    # t.add(14)
    # t.in_order(t.root)
    # t.threaded_node(t.root)

    # 手动创建结点--只是为了更好测试线索化有没有成功
    t1 = TreeNode(1)
    t2 = TreeNode(3)
    t3 = TreeNode(6)
    t4 = TreeNode(8)
    t5 = TreeNode(10)
    t6 = TreeNode(14)
    t1.left = t2
    t1.right = t3
    t2.left = t4
    t2.right = t5
    t3.left = t6
    print("原来的二叉树中序遍历为:")
    t.in_order(t1)
    # 线索化二叉树
    t.threaded_node(t1)
    # 测试:以值为10 的结点来测试
    left_node = t5.left
    print()
    print("10 的前驱结点是:%d" % left_node.val)  # 3
    right_node = t5.right
    print("10 的后继结点是:%d" % right_node.val)  # 1
    
'''输出结果
原来的二叉树中序遍历为:
8 3 10 1 14 6 
10 的前驱结点是:3
10 的后继结点是:1
'''

在这里插入图片描述

  • 可以比对结果,如上图,线索化二叉树后,10的前驱结点是3,10的后继结点是1,说明我们线索化二叉树,成功,接下里就要完成:线索化存储二叉树的遍历 了↓↓↓

线索化存储二叉树的遍历

在这里插入图片描述

class TreeNode(object):
    def __init__(self, val=-1):
        self.val = val
        self.left = None
        self.right = None
        # 新增类型指针
        # 规定:
        # 如果left_type==0 表示指向的是左子树,如果是1 则表示指向前驱结点
        # 如果right_type==0 表示指向的是右子树,如果是1 怎表示指向后继结点
        self.left_type = 0
        self.right_type = 0


class ThreadedBinaryTree(object):
    def __init__(self):
        self.root = None
        # 在递归进行线索化,总是保留前一个结点
        self.pre = None  # 为实现线索化,需要创建给指向当前结点的前驱结点指针

    # 添加结点测试
    def add(self, val):
        node = TreeNode(val)
        if self.root is None:
            self.root = node
            return
        queue = [self.root]
        while queue:
            temp_node = queue.pop(0)
            if temp_node.left is None:
                temp_node.left = node
                return
            else:
                queue.append(temp_node.left)
            if temp_node.right is None:
                temp_node.right = node
                return
            else:
                queue.append(temp_node.right)

    # 中序遍历测试
    def in_order(self, node):
        if node is None:
            return
        self.in_order(node.left)
        print(node.val, end=' ')
        self.in_order(node.right)

    # 中序遍历线索化二叉树
    def threaded_in_order(self, node):
        if node is None:
            return
        temp_node = node
        while temp_node:
            # 循环的找到left_type=1的结点,第一个找到就是值为8的结点
            # 后面随着遍历而变化,因为当left_type=1时,说明该结点是按照线索化处理后的有效结点
            while temp_node.left_type == 0:  # 从根结点开始向左找,找到第一个1停止
                temp_node = temp_node.left
            # 打印当前这个结点
            print(temp_node.val, end=" ")
            # 如果当前结点的右指针指向的是后继结点,就一直输出
            while temp_node.right_type == 1:
                # 获取到当前结点的后继结点
                temp_node = temp_node.right
                print(temp_node.val, end=" ")
            # 如果不等于1了,就替换这个遍历的结点
            temp_node = temp_node.right

    # 二叉树进行中序线索化的方法
    def threaded_node(self, node):  # node: 就是当前需要线索化的结点
        if node is None:
            return
        # 先线索化左子树
        self.threaded_node(node.left)
        # 线索化当前结点

        # 处理当前结点的前驱结点
        if node.left is None:  # 如果当前结点左子结点为空
            node.left = self.pre  # 让当前结点的左指针指向前驱结点
            node.left_type = 1  # 修改当前结点的左指针类型 为 前驱结点

        # 处理当前结点的后继结点
        if self.pre and self.pre.right is None:
            self.pre.right = node  # 让前驱结点的右指针指向当前结点
            self.pre.right_type = 1  # 修改前驱结点的右指针类型
        self.pre = node  # 每处理一个结点后,让当前结点是下一个结点的前驱结点
        # 线索化右子树
        self.threaded_node(node.right)


if __name__ == '__main__':
    # 调用add 自动创建结点
    t = ThreadedBinaryTree()
    '''
    t.add(1)
    t.add(3)
    t.add(6)
    t.add(8)
    t.add(10)
    t.add(14)
    t.in_order(t.root)
    t.threaded_node(t.root)
    print()
    t.threaded_in_order(t.root)
    '''

    # 手动创建结点--只是为了更好测试线索化有没有成功
    t1 = TreeNode(1)
    t2 = TreeNode(3)
    t3 = TreeNode(6)
    t4 = TreeNode(8)
    t5 = TreeNode(10)
    t6 = TreeNode(14)
    t1.left = t2
    t1.right = t3
    t2.left = t4
    t2.right = t5
    t3.left = t6
    print("原来的二叉树中序遍历为:")
    t.in_order(t1)
    # 线索化二叉树
    t.threaded_node(t1)
    # 测试:以值为10 的结点来测试
    left_node = t5.left
    print()
    print("10 的前驱结点是:%d" % left_node.val)  # 3
    right_node = t5.right
    print("10 的后继结点是:%d" % right_node.val)  # 1
    print("线索化二叉树的中序遍历结果为:")
    t.threaded_in_order(t1)
    
''' 输出结果为:
原来的二叉树中序遍历为:
8 3 10 1 14 6 
10 的前驱结点是:3
10 的后继结点是:1
线索化二叉树的中序遍历结果为:
8 3 10 1 14 6 
'''
  • 两次遍历的结果一致,说明我们成功了,这次实现秒就妙在,新增了类型指针,还可以用来作为新的判断条件!
发布了146 篇原创文章 · 获赞 37 · 访问量 7857

猜你喜欢

转载自blog.csdn.net/storyfull/article/details/103744339