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

猜你喜欢

转载自www.cnblogs.com/MartinLwx/p/9644473.html