zoukankan      html  css  js  c++  java
  • Python的二叉树实现

    二叉树需要实现的功能及思路

    1. 找到最小值

      没什么好说的就是二叉树最左下的顶点

    2. 找到最大值

      没什么好说的就是二叉树最右下的顶点

    3. 插入

      分情况,如果二叉树为空那么直接直接设置成根节点就好了。否则就逐层向下,比当前小的往左边方向,否则往右边方向

    4. 删除

      为了要实现删除的功能,我们先定义一个方法,它返回的是被删除的节点和它的父节点,返回形式为tuple,即(parent,node)

      这个就比较复杂了,分三种情况:

      1. 被删除的节点没有子节点

        再分为两种:

        • 有父节点:看是父节点的左节点还是右节点,将对应的赋为None
        • 无父节点:很明显这就是根节点本身了,直接赋为None就好了
      2. 被删除的节点有1个子节点

        将返回的父节点直接链接到被删除节点的子节点,用一张图说明就是:

        具体去代码中感受就好

      3. 被删除的节点有2个子节点

        这种情况要么找左子树的最右边节点或者右子树的最左节点(由二叉树的定义可知)

    5. 查找某个节点

      就是从根节点开始,根据大小关系逐层往下找就好了

    6. 先序/中序/后序遍历

      代码不同的一行在于输出当前节点的语句的位置,具体看代码

    7. 宽度优先遍历

      也就是逐层遍历,通过队列实现,将根节点入队,然后扫描左右节点,分别入队,这样出队的时候一定是左边的节点先出来,子节点在入队。入队-出队持续到队列为空为止。

    代码

    from collections import deque
    
    class Node:
        def __init__(self, data=None):
            self.data = data
            self.left_child = None
            self.right_child = None
    
    class Tree:
        def __init__(self):
            self.root_node = None
    
        def find_min(self):
            current = self.root_node
            while current.left_child:
                current = current.left_child
            return current
    
        def find_max(self):
            current = self.root_node
            while current.right_child:
                current = current.right_child
    
            return current
    
        def insert(self, data):
            node = Node(data)
            if self.root_node is None:
                self.root_node = node
            else:
                current = self.root_node
                parent = None
                while True:
                    parent = current
                    if node.data < current.data:
                        current = current.left_child
                        if current is None:
                            parent.left_child = node
                            return
                    else:
                        current = current.right_child
                        if current is None:
                            parent.right_child = node
                            return
    
        def get_node_with_parent(self, data):
            current = self.root_node
            parent = None
            if current is None:
                return (parent,None)
            while True:
                if current.data == data:
                    return (parent,current)
                elif current.data > data:
                    parent = current
                    current = current.left_child
                else:
                    parent = current
                    current = current.right_child
    
            return (parent,current)
    
        def remove(self, data):
            parent, node = self.get_node_with_parent(data)
    
            if parent is None and node is None:
                return False
    
            children_count = 0
    
            if node.left_child and node.right_child:
                children_count = 2
            elif (node.left_child is None) and (node.right_child is None):
                children_count = 0
            else:
                children_count = 1
    
            if children_count == 0:
                if parent:
                    if parent.right_child is node:
                        parent.right_child = None
                    else:
                        parent.left_child = None
                else:                                   #只有根节点
                    self.root_node = None
            elif children_count == 1:
                '''要删除的节点有一个子节点'''
                next_node = None
                if node.left_child:
                    next_node = node.left_child
                else:
                    next_node = node.right_child        #确定子节点是在左边还是在右边
    
                if parent:
                    if parent.left_child is node:
                        parent.left_child = next_node
                    else:
                        parent.right_child = next_node
                else:
                    self.root_node = next_node
            else:
                '''要么找左子树的最右边节点或者右子树的最左节点'''
                parent_of_leftmost_node = node
                leftmost_node = node.right_child        #右边的顶点才会比要被删除的节点大
                while leftmost_node.left_child:
                    parent_of_leftmost_node = leftmost_node
                    leftmost_node = leftmost_node.left_child        #找到最左下的顶点,保持平衡性,这个是右子树的最小节点
    
                node.data = leftmost_node.data
                if parent_of_leftmost_node.left_child == leftmost_node:
                    parent_of_leftmost_node.left_child = leftmost_node.right_child
                else:
                    parent_of_leftmost_node.right_child = leftmost_node.right_child
    
        def search(self, data):
            current = self.root_node
            while True:
                if current is None:
                    return None
                elif current.data == data:
                    return data
                elif current.data > data:
                    current = current.left_child
                else:
                    current = current.right_child
    
        def inorder(self, root_node):
            current = root_node
            if current is None:
                return
            self.inorder(current.left_child)
            print(current.data)
            self.inorder(current.right_child)
    
        def preorder(self, root_node):
            current = root_node
            if current is None:
                return
            print(current.data)
            self.preorder(current.left_child)
            self.preorder(current.right_child)
    
        def postorder(self, root_node):
            current = root_node
            if current is None:
                return
            self.postorder(current.left_child)
            self.postorder(current.right_child)
            print(current.data)
    
        def breadth_first_traversal(self):
            list_of_nodes = []
            traversal_queue = deque([self.root_node])
            while len(traversal_queue) > 0:
                node = traversal_queue.popleft()
                list_of_nodes.append(node.data)
    
                if node.left_child:
                    traversal_queue.append(node.left_child)
    
                if node.right_child:
                    traversal_queue.append(node.right_child)
            return list_of_nodes
    
  • 相关阅读:
    CSS设置行高
    微信小程序-水平垂直居中
    CSS布局
    HTML学习笔记—标签
    微信小程序--通过请求网页获取信息并显示
    docker 安装完mysql 后客户端无法访问
    Docker
    docker安装成功启动失败
    嵌入式Servlet容器自动配置和启动原理
    springboot外置的Servlet容器
  • 原文地址:https://www.cnblogs.com/MartinLwx/p/9644473.html
Copyright © 2011-2022 走看看