python二叉查找树

二叉查找树是二叉树的进化型,特点就是前序遍历得到的数组是递增关系,通俗点就是左孩子最小,父节点次之,右孩子最大

这里仿照之前写二叉树的过程来,首先定义两个类

class Node():
    def __init__(self,item):
        self.item=item
        self.left=None
        self.right=None

class Tree():
    
        def __init__(self):
            self.root=None

 

按二叉树的建立过程现在需要一个add方法来添加节点,二分查找树在这里就开始和二叉树有了不同

(下面简称二叉查找树BST,每次写起来太长了)

BST为了保证数中节点的大小顺序不被打乱,每次都把新的节点插入到叶子结点下,每次这么做前需要先查找到插入的位置,所以我们这里先要实现查找方法,由于BST内部节点有序,所以这里仿照二分查找

def search(self,node,item):
    if not node:
        return None
    if node.item==item:
        return node
    elif node.item<item:
        return self.search(node.right,item)
    else:
        return self.search(node.left,item)      
                

现在来实现插入

def add(self,node,item):
            if not node:
                return Node(item)
            if node.item==item:
                return
            else:
                if node.item<item:
                    node.right=Node(item)

                else:
                    node.left=Node(item)

            return node

最难的操作来了,删除要怎么来实现,删除的节点未必是叶子结点,所以产生了删除非叶子结点后如何维护BST的问题

叶子结点和只有1个孩子的节点的删除都比较好操作,直接删除并把孩子接上原来的位置就好,问题出在左右孩子都存在的

点上

 

我的解决方案是这样的,找出删除节点前序遍历的前一个节点来替换,为什么这么做呢?

根据BST的特点,根节点前序遍历的前一个节点一定是左子树的最右下角节点(过几天把图补上,CSND画不了图这个就很烦)

这个节点的值一定是大于根节点左子树的所有值的,不然也不会在最右下角,同时也小于根节点所有右子树的节点下面我们来想办法实现(注意这个点未必是叶子结点,我一开始这么写结果错了很久)

《python二叉查找树》

 

def remove(self,node,item):
     if not node:
          return None

     else:
          if node.item==item:
               return self.delete(node)
          elif node.item<item:
               return self.remove(node.right,item)
          else:
               return self.remove(node.left,item)

def delete(p):
     if not p.left:                 #判断左子树位空,重接右子树
          q=p
          p=p.reft
          del(q)

     elif not p.right:              #判断右子树为空,重接左子树
          q=p
          p=p.light
          del(q)

     else:                            #左右子树都存在
          s=p.left
          while s.right:             #先往左,在往右边到头
               q=s
               s=s.right

          p.item=s.item           #覆盖待删除点的值

          if q!=p:                 #这里需要判断待删除点和用来覆盖的点的关系
               q.right=s.left
          else:
               q.left=s.left
          del s

这里最难理解的是最后拼接子树的部分,这里实际上是判断了待删除节点是否为s节点的父节点,如果是的话,左孩子可以无缝连接上去,如果不是,s的左孩子就需要拼接给s的父节点作为右孩子(因为s肯定没右孩子,父节点刚好也需要一个右孩子补充失去的s节点)

 《python二叉查找树》

 《python二叉查找树》

 《python二叉查找树》

 《python二叉查找树》

 《python二叉查找树》

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/wzngzaixiaomantou/article/details/81432033
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞