二叉搜索树(BST)

class TreeNode():
    def __init__(self,key,val,left=None,right=None,parent=None):
        self.key=key
        self.payload=val
        self.leftChild=left
        self.rightChild=right
        self.parent=parent
    def hasLeftChild(self):
        return self.leftChild

    def hasRightChild(self):
        return self.rightChild

    def isLeftChild(self):
        return self.parent and self.parent.leftChild==self

    def isRightChild(self):
        return self.parent and self.parent.rightChild == self

    def isLeaf(self):
        return not(self.leftChild or self.rightChild)

    def hasAnyChild(self):
        return  self.leftChild or self.rightChild

    def hasBothChild(self):
        return self.rightChild and self.leftChild

    def replaceNodeData(self,key,value,lc,rc):
        self.key=key
        self.payload=value
        self.rightChild=rc
        self.leftChild=lc
        if self.hasLeftChild():
            self.leftChild.parent=self
        if self.hasRightChild():
            self.rightChild=self

    def findSuccessor(self):
        '''寻找后继结点'''
        succ=None
        if self.hasRightChild():
            succ=self.rightChild.findMin()
        else:
            if self.parent:
                if self.isLeftChild():
                    succ=self.parent
                else:
                    self.parent.rightChild=None
                    succ=self.parent.findSuccessor()
                    self.parent.rightChild=self
        return succ

    def findMin(self):
        current=self
        while current.hasLeftChild():
            current=current.leftChild
        return current

    def spliceOut(self):
        if self.isLeaf():       #叶子节点
            if self.isLeftChild:        #是左孩子
                self.parent.leftChild=None
            else:       #是右孩子
                self.parent.rightChild=None
        elif self.hasAnyChild():
            if self.hasLeftChild():
                if self.isLeftChild():
                    self.parent.leftChild=self.leftChild
                else:
                    self.parent.rightChild=self.leftChild
                self.leftChild.parent=self.parent
            else:
                if self.isLeftChild():
                    self.parent.leftChild=self.rightChild
                else:
                    self.parent.rightChild=self.rightChild
                self.rightChild.parent=self.parent





class BinarySearchTree:

    def __init__(self):
        self.root=None
        self.size=0

    def length(self):
        return self.size

    def __len__(self):
        return self.size

    def __iter__(self):
        return self.root.__iter__()

    def put(self,key,val):
        '''为BST插入新节点'''
        if self.root:
            self._put(key,val,self.root)
        else:
            self.root=TreeNode(key,val)
        self.size+=1

    def _put(self,key,val,currentNode):
        if key<currentNode.key:
            #递归处理左子树
            if currentNode.hasLeftChild():
                self._put(key,val,currentNode.leftChild)
            else:   #如果没有左孩子则插入到这个节点的左孩子上(递归出口)
                currentNode.leftChild=TreeNode(key,val,parent=currentNode)
        else:
            #递归处理右子树
            if currentNode.hasRightChild():
                self._put(key,val,currentNode.rightChild)
            else:
                currentNode.rightChild=TreeNode(key,val,parent=currentNode)

    def __setitem__(self, key, value):
        '''调用put方法来重载运算符[],可以像字典一样添加节点'''
        self.put(key,value)

    def get(self,key):
        '''查找键对应的值'''
        if self.root:   #树不为空
            res=self._get(key,self.root)
            if res:     #如果找到了
                return res.payload
            else:
                return None
        else:
            return None

    def _get(self,key,currentNode):
        if not currentNode:     #如果currentNode为空节点
            return None
        elif currentNode.key==key:     #找到了这个key(递归出口)
            return currentNode
        elif key<currentNode.key:      #如果key比当前节点的key小则在左子树上找
            self._get(key,currentNode.leftChild)
        else:       #否则在右子树上找
            return self._get(key,currentNode.rightChild)

    def __getitem__(self, item):
        '''可以像字典一样查找二叉树'''
        return self.get(item)

    def __contains__(self, item):
        '''此方法重载了运算符 in 检查树中是否有某个键'''
        if self._get(item,self.root):
            return True
        else:
            return False

    def createByDict(self,dict):
        '''用字典构建BST'''
        for key,value in dict.items():
            self.put(key,value)

    def createByList(self,list):
        '''用列表构建BST,值为None'''
        for key in list:
            self.put(key,None)

    def delete(self,key):
        if self.size>1:     #不只有根节点
            nodeToRemove=self._get(key,self.root)
            if nodeToRemove:        #找到这个节点,删除并返回
                self.remove(nodeToRemove)
                self.size-=1
                return nodeToRemove
            else:       #找不到这个节点抛出异常
                raise KeyError('Error,key not in tree')

        elif self.size==1 and self.root.key==key:       #只有一个根节点并且根节点就是要找的key
            nodeToRemove=self.root
            self.root=None
            self.size-=1
            return nodeToRemove

        else:       #只有一个根节点但不是要找的key,抛出异常
            raise KeyError('Error,key not in tree')

    def __delitem__(self, key):
        '''使对象可以用del删除key'''
        self.delete(key)

    def remove(self,currentNode):
        if currentNode.isLeaf():    #叶子节点
            if currentNode.isLeftChild:
                currentNode.parent.leftChild=None
            else:
                currentNode.parent.rightChild=None
        elif currentNode.hasBothChild():    #内部
            succ=currentNode.findSuccessor()
            succ.spliceOut()
            currentNode.key=succ.key
            currentNode.payload=currentNode.payload
        else:   #只有一个子节点
            if currentNode.hasLeftChild():
                if currentNode.isLeftChild():
                    currentNode.leftChild.parent=currentNode.parent
                    currentNode.parent.leftChild=currentNode.leftChild
                elif currentNode.isRightChild():
                    currentNode.leftChild.parent=currentNode.parent
                    currentNode.parent.rightChild=currentNode.leftChild
                else:
                    currentNode.replaceNodeData(currentNode.leftChild.key,
                                                currentNode.leftChild.payload,
                                                currentNode.leftChild.leftChild,
                                                currentNode.leftChild.rightChild)
            else:
                if currentNode.isLeftChild():
                    currentNode.rightChild.parent=currentNode.parent
                    currentNode.parent.leftChild=currentNode.rightChild
                elif currentNode.isRightChild():
                    currentNode.rightChild.parent=currentNode.parent
                    currentNode.parent.rightChild=currentNode.rightChild
                else:
                    currentNode.replaceNodeData(currentNode.rightChild.key,
                                                currentNode.rightChild.payload,
                                                currentNode.rightChild.leftChild,
                                                currentNode.rightChild.rightChil)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值