美文网首页
6.搜索树完整代码

6.搜索树完整代码

作者: M_小七 | 来源:发表于2019-12-26 10:35 被阅读0次

BinarySearchTree类

class BinarySearchTree:

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

    def length(self):
        return self.size

    def __len__(self):
        return self.size

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

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

    def put(self,key,val):

        if self.root:
            self._put(key,val,self.root)
        else:
            self.root = TreeNode(key,val)

        self.size+=1

    def _put(self,key,val,currentNode):
        # print('BinarySearchTree _put')
        if key < currentNode.key:
            if currentNode.hasLeftChild():
                self._put(key,val,currentNode.leftChild)
            else:
                currentNode.leftChild = TreeNode(key,val,parent=currentNode)
        elif key > currentNode.key:
            if currentNode.hasRightChild():
                self._put(key,val,currentNode.rightChild)
            else:
                currentNode.rightChild = TreeNode(key,val,parent=currentNode)
        else:
            currentNode.payload = val
            self.size-=1

    def __setitem__(self, key, value):
        self.put(key,value)

    def _get(self,key,currentNode):
        if not currentNode:
            return None
        if currentNode.key == key:
            return currentNode
        elif key < currentNode.key:
            return self._get(key,currentNode.leftChild)
        else:
            return self._get(key,currentNode.rightChild)

    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 __getitem__(self, key):
        return self.get(key)

    def __contains__(self, key):
        if self._get(key,self.root):
            return True
        else:
            return False



    def remove(self,current_node):
        if current_node.isLeaf():
            if current_node == current_node.parent.leftChild:
                current_node.parent.leftChild = None
            else:
                current_node.parent.rightChild = None
        elif current_node.hasBothChildren():
            succ = current_node.findSuccessor()
            current_node.key = succ.key
            current_node.payload = succ.payload
            succ.spliceOut()
        else:
            if current_node.hasLeftChild():
                if current_node.isLeftChild():
                    current_node.parent.leftChild = current_node.leftChild
                    current_node.leftChild.parent = current_node.parent
                elif current_node.isRightChild():
                    current_node.parent.rightChild = current_node.leftChild
                    current_node.leftChild.parent = current_node.parent
                else:
                    current_node.replaceNodeData(current_node.leftChild.key,current_node.leftChild.payload,
                                                 current_node.leftChild.leftChild,current_node.leftChild.rightChild)
            else:
                if current_node.isLeftChild():
                    current_node.parent.leftChild = current_node.rightChild
                    current_node.rightChild.parent = current_node.parent
                elif current_node.isRightChild():
                    current_node.parent.rightChild = current_node.rightChild
                    current_node.rightChild.parent = current_node.parent
                else:
                    current_node.replaceNodeData(current_node.rightChild.key,current_node.rightChild.payload,
                                                 current_node.rightChild.leftChild,current_node.rightChild.RightChild)


    def delete(self,key):
        if self.size > 1:
            nodeToRemove = self._get(key,self.root)
            if nodeToRemove:
                self.remove(nodeToRemove)
                self.size -= 1
            else:
                raise KeyError('Error, key not in the tree')
        elif self.size == 1 and self.root.key == key:
            self.root = None
            self.size -= 1
        else:
            raise KeyError('Error, key not in the tree')

if __name__ == '__main__':
    tree = BinarySearchTree()
    for i in range(1,16):
        tree[i] = i
    # tree[18] = 'wangwu'
    # tree[33] = 'lisi'
    # tree[55] = 'ddd'
    # tree[66] = 'zhangsan'
    # tree[99] = 'hanh'
    # tree = BinarySearchTree()
    # tree[17] = 'zhangsan'
    # tree[5] = 'lisi'

TreeNode类

class TreeNode:
    '''A node for the Binary Search Tree '''

    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
        self.balanceFactor = 0

    def height(self):
        height_l = 0
        height_r = 0
        if self.isLeaf():
            return 0
        if self.leftChild:
            height_l = self.leftChild.height()
        if self.rightChild:
            height_r = self.rightChild.height()
        return max(height_l,height_r) + 1

    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 isRoot(self):
        return not self.parent

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

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

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

    def replaceNodeData(self,key,value,lc,rc):
        self.key = key
        self.payload = value
        self.leftChild = lc
        self.rightChild = rc
        if self.hasLeftChild():
            self.leftChild.parent = self
        if self.hasRightChild():
            self.rightChild.parent = 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 spliceOut(self):
        if self.isLeaf():
            if self.isLeftChild():
                self.parent.leftChild = None
            else:
                self.parent.rightChild = None
        elif self.hasAnyChildren():#self.hasRightChild()
            if self.hasLeftChild():
                if self.isLeftChild():
                    self.parent.leftChild = self.leftChild
                    self.leftChild.parent = self.parent
                else:
                    self.parent.rightChild = self.leftChild
                    self.leftChild.parent = self.parent
            else:
                if self.isLeftChild():
                    self.parent.leftChild = self.rightChild
                    self.rightChild.parent = self.parent
                else:
                    self.parent.rightChild = self.rightChild
                    self.rightChild.parent = self.parent


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

    def __iter__(self):
        if self:
            if self.hasLeftChild():
                for node in self.leftChild:
                    yield node
            yield self.key
            if self.hasRightChild():
                for node in self.rightChild:
                    yield node

AvlTree类

class AvlTree(BinarySearchTree):
    def rotateLeft(self, rotRoot):
        newRoot = rotRoot.rightChild
        rotRoot.rightChild = newRoot.leftChild
        if newRoot.leftChild != None:
            newRoot.leftChild.parent = rotRoot
        newRoot.parent = rotRoot.parent
        if rotRoot.isRoot():
            self.root = newRoot
        else:
            if rotRoot.isLeftChild():
                rotRoot.parent.leftChild = newRoot
            else:
                rotRoot.parent.rightChild = newRoot
        newRoot.leftChild = rotRoot
        rotRoot.parent = newRoot
        rotRoot.balanceFactor = rotRoot.balanceFactor + 1 - min(
            newRoot.balanceFactor, 0)
        newRoot.balanceFactor = newRoot.balanceFactor + 1 + max(
            rotRoot.balanceFactor, 0)

    def rotateRight(self, rotRoot):
        newRoot = rotRoot.leftChild
        rotRoot.leftChild = newRoot.rightChild
        if newRoot.rightChild != None:
            newRoot.rightChild.parent = rotRoot
        newRoot.parent = rotRoot.parent
        if rotRoot.isRoot():
            self.root = newRoot
        else:
            if rotRoot.isRightChild():
                rotRoot.parent.rightChild = newRoot
        newRoot.rightChild = rotRoot
        rotRoot.parent = newRoot
        rotRoot.balanceFactor = rotRoot.balanceFactor + 1 - min(
            newRoot.balanceFactor, 0)
        newRoot.balanceFactor = newRoot.balanceFactor + 1 + max(
            rotRoot.balanceFactor, 0)

    # 如果子树需要左旋,首先检查右子树的平衡因子。如果右子树左倾,就对右子树做一次右旋,再围绕原节点做一次左旋。
    # 如果子树需要右旋,首先检查左子树的平衡因子。如果左子树右倾,就对左子树做一次左旋,再围绕原节点做一次右旋。
    def rebalance(self,node):
        if node.balanceFactor < 0:
            if node.rightChild.balanceFactor > 0:
                self.rotateRight(node.rightChild)
                self.rotateLeft(node)
            else:
                self.rotateLeft(node)
        elif node.balanceFactor > 0:
            if node.leftChild.balanceFactor < 0:
                self.rotateLeft(node.leftChild)
                self.rotateRight(node)
            else:
                self.rotateRight(node)

    def updateBalance(self, node):
        if node.balanceFactor > 1 or node.balanceFactor < -1:
            self.rebalance(node)
            return
        if node.parent == None:
            return
        else:
           if node.isLeftChild():
               node.parent.balanceFactor += 1
           elif node.isRightChild():
               node.parent.balanceFactor -= 1

           if node.parent.balanceFactor != 0:
               self.updateBalance(node.parent)


    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)
                self.updateBalance(currentNode.leftChild)

        elif key > currentNode.key:
            if currentNode.hasRightChild():
                self._put(key, val, currentNode.rightChild)
            else:
                currentNode.rightChild = TreeNode(key, val, parent=currentNode)
                self.updateBalance(currentNode.rightChild)
        else:
            currentNode.payload = val
            self.size -= 1


if __name__ == '__main__':
    tree = AvlTree()
    for i in range(1,16):
        tree[i] = i
    # tree[18] = 'wangwu'
    # tree[33] = 'lisi'
    # tree[55] = 'ddd'
    # tree[66] = 'zhangsan'
    # tree[99] = 'hanh'

    print(tree.height())

相关文章

网友评论

      本文标题:6.搜索树完整代码

      本文链接:https://www.haomeiwen.com/subject/hfjkoctx.html