python小练习13 -- 二叉树实现

"""
    二叉树:插入 删除 查找
"""
from exer4 import SQueue # 见队列实现
import random


class Node:
    """
    节点类,
    """
    __slots__ = ["__value", "__left", "__right"]

    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

    @property
    def value(self):
        return self.__value

    @value.setter
    def value(self, value):
        if isinstance(value, int):
            self.__value = value
        else:
            raise ValueError("value should be an instance of int")

    @property
    def left(self):
        return self.__left

    @left.setter
    def left(self, node):
        if isinstance(node, Node) or node is None:
            self.__left = node
        else:
            raise ValueError("node should be an instance of Node")

    @property
    def right(self):
        return self.__right

    @right.setter
    def right(self, node):
        if isinstance(node, Node) or node is None:
            self.__right = node
        else:
            raise ValueError("node should be an instance of Node")


class BiTree:
    """
    二叉树类:传入一个整数,把这个值生成的节点插入到二叉树中,这个节点的值,大于左孩子的值,小于等于右孩子的值
    """

    def __init__(self):
        self.__root = None

    def make_bitree(self, lis):
        """
        用传入列表中的节点生成一棵二叉树
        :param lis:
        :return: 返回生成二叉树的根节点
        """
        if not isinstance(lis, list):
            raise TypeError("lis should be a instance of list")

        root = lis[0]
        root.left = None
        root.right = None

        for item in lis[1:]:
            item.left = None
            item.right = None
            self.__insert2(item, root)

        return root

    def find_node(self, value):
        """
        查找二叉树中是否存在值为value的节点,存在返回这个节点
        :param value: 传入值
        :return: (bool, node)
        """
        root = self.__root

        while root is not None and value != root.value:
            if root.value > value:
                root = root.left
            else:
                root = root.right

        if root is None:
            return False, None
        else:
            return True, root

    def __hierarchy_tranverse(self, node_queue):
        """
        传入同一深度的节点组成的队列,按从同一深度从左到右,深度从上到下排列的node组成的数组
        :param node_queue:
        :return:
        """
        queue = SQueue(100)
        lst = []
        while not node_queue.is_empty():
            node = node_queue.dequeue()
            lst.append(node)
            if node.left is not None:
                queue.enqueue(node.left)
            if node.right is not None:
                queue.enqueue(node.right)
        if not queue.is_empty():
            rtn_lst = self.__hierarchy_tranverse(queue)
            lst.extend(rtn_lst)
        return lst

    def hirerarchy_tranverse(self):
        """
        层次遍历,返回一个列表,列表中节点按从上倒下从左到右顺序在列表中排列
        :return:
        """
        queue = SQueue(100)
        queue.enqueue(self.__root)
        return self.__hierarchy_tranverse(queue)

    def delete_value(self, value):
        """
        删除值为value的节点,返回(bool, node),如果不存在这个值的节点则返回(False, None)
        :param value:传入值
        :return:
        """
        rtn, node = self.find_node(value)

        if not rtn:
            return False, None

        prev, sid = self.find_previous_node(node)

        if prev is None:
            lis = self.hirerarchy_tranverse()
            self.__root = self.make_bitree(lis[1:])
        else:
            if node.left is None and node.right is None:
                if sid == 0:
                    prev.left = None
                else:
                    prev.right = None
            elif node.left is not None and node.right is not None:
                queue = SQueue()
                queue.enqueue(node)
                lis = self.__hierarchy_tranverse(queue)
                newroot = self.make_bitree(lis[1:])
                if sid == 0:
                    prev.left = newroot
                else:
                    prev.right = newroot
            elif node.left is not None:
                if sid == 0:
                    prev.left = node.left
                else:
                    prev.right = node.left
            else:
                if sid == 0:
                    prev.left = node.right
                else:
                    prev.right = node.right
        return True, node

    def __find_previous_node(self, node, root):
        """
         从root开始,查找node节点的父节点,如果找到,返回这个父节点以及是父节点的左节点(0)还是右节点(1)
        这个节点的父节点不存在,则返回(None,-1)
        :param node:要查找的节点
        :param root: 从这个节点开始查找
        :return: (父节点,左节点/右节点)
        """
        if root is None or root == node:
            return None, -1
        elif root.left == node:
            return root, 0
        elif root.right == node:
            return root, 1

        if root.left is not None:
            (prev, sid) = self.__find_previous_node(node, root.left)
            if prev is not None:
                return prev, sid

        return self.__find_previous_node(node, root.right)

    def find_previous_node(self, node):
        return self.__find_previous_node(node, self.__root)

    def insert2(self, value):
        node = Node(value)
        if self.__root is None:
            self.__root = node
        else:
            self.__insert2(node, self.__root)

    def __insert2(self, node, root):
        """
        采用递归方式插入
        :param node:
        :param root:
        :return:
        """
        if root is None:
            return
        if root.left is None and root.right is None:
            if root.value > node.value:
                root.left = node
            else:
                root.right = node
        elif root.left is not None and root.right is None:
            if root.value > node.value:
                self.__insert2(node, root.left)
            else:
                root.right = node
        elif root.left is None and root.right is not None:
            if root.value > node.value:
                root.left = node
            else:
                self.__insert2(node, root.right)
        else:
            if root.value > node.value:
                self.__insert2(node, root.left)
            else:
                self.__insert2(node, root.right)

    def insert(self, value):
        """
        向二叉树中插入一个值
        :param value:
        :return: 无
        """
        node = Node(value)
        if self.__root is None:
            self.__root = node
        else:
            self.__insert(node, self.__root)

    def __insert(self, node, root):
        """
        把传入的节点插入到以root为根的二叉树中
        :param node:
        :param root:
        :return:
        """
        while root is not None:
            current = root
            if node.value < root.value:
                root = root.left
            else:
                root = root.right
        if node.value < current.value:
            current.left = node
        else:
            current.right = node

    def __front_tranverse(self, root):
        if root is None:
            return
        print("%5d" % root.value, end=" ")
        if root.left is None and root.right is None:
            return

        self.__front_tranverse(root.left)
        self.__front_tranverse(root.right)

    def __middle_tranverse(self, root):
        if root is not None:
            if root.left is None:
                print("%5d" % root.value, end=" ")
                self.__middle_tranverse(root.right)
            else:
                self.__middle_tranverse(root.left)
                print("%5d" % root.value, end=" ")
                self.__middle_tranverse(root.right)

    def __last_tranverse(self, root):
        if root is not None:
            self.__last_tranverse(root.left)
            self.__last_tranverse(root.right)
            print("%5d" % root.value, end=" ")

    def last_tranverse(self):
        """
        后序遍历二叉树
        :return:
        """
        self.__last_tranverse(self.__root)
        print()

    def middle_tranverse(self):
        """中序遍历二叉树"""
        self.__middle_tranverse(self.__root)
        print()

    def front_tranverse(self):
        """
        后续遍历二叉树
        :return:
        """
        self.__front_tranverse(self.__root)
        print()


if __name__ == "__main__":
    """二叉树测试"""
    bitree1 = BiTree()
    bitree2 = BiTree()
    i = 1
    # tmp = []
    # while i < 15:
    #     rnd = random.randint(1, 100)
    #     if rnd not in tmp:
    #         tmp.append(rnd)
    #     else:
    #         continue
    #     i += 1

    tmp = [84, 19, 47, 81, 51, 62, 74, 31, 20, 27, 57, 44, 85, 88]
    print("原数组:", tmp)
    for val in tmp:
        bitree1.insert(val)
        bitree2.insert2(val)

    print("先序遍历:", end=" ")
    bitree1.front_tranverse()
    print("中序遍历:", end=" ")
    bitree1.middle_tranverse()
    print("后序遍历:", end=" ")
    bitree1.last_tranverse()
    print("层级遍历:", end=" ")
    node_lst = bitree1.hirerarchy_tranverse()
    for node in node_lst:
        print("%5d" % node.value, end=" ")
    print()

    """测试二叉树递归插入:"""
    print("*" * 20)
    print("测试二叉树递归插入")

    print("先序遍历:", end=" ")
    bitree2.front_tranverse()
    print("中序遍历:", end=" ")
    bitree2.middle_tranverse()
    print("后序遍历:", end=" ")
    bitree2.last_tranverse()
    print("层级遍历:", end=" ")
    lst = bitree2.hirerarchy_tranverse()
    for node in lst:
        print("%5d" % node.value, end=" ")
    print()

    """测试查找"""
    print("测试查找:")
    rtn, node = bitree1.find_node(51)
    if rtn:
        print("value=%d" % node.value)

    previous, side = bitree1.find_previous_node(node)

    if previous is not None:
        print("side:%d value:%d" % (side, previous.value))

    rtn, node = bitree1.delete_value(85)
    if rtn:
        print("删除节点:%d" % node.value)
        print("先序遍历:", end=" ")
        bitree1.front_tranverse()
        rtn2, node2 = bitree1.find_node(88)
        if rtn2:
            prev2, sid2 = bitree1.find_previous_node(node2)
            print("被删除节点的前一个节点:%d,side:%d" % (prev2.value, sid2))
测试结果:

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值