数据结构与算法(25)——二叉查找树BST

  • 二叉查找树

性质:比父节点小的key都出现在左子树,比父 节点大的key都出现在右子树。

 

 

❖按照70,31,93,94,14,23,73的顺序插入

❖首先插入的70成为树根 31比70小,

放到左子节点 93比70大,

放到右子节点 94比93大,

放到右子节点 14比31小,

放到左子节点 23比14大,

放到其右 73比93小,

放到其左

❖注意:插入顺序不同,生成的BST也不同

  • 代码实现
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__()

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

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

    def hasBothChild(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 put(self, key, val): #插入key构造BST
        if self.root:
            self._put(key, val, self.root)
        else:
            self.root = TreeNode(key, val)
        self.size = self.size + 1
    def _put(self, key, val, currentNode):
        '''
        如果key比currentNode小,那么_put到左子树
        但如果没有左子树,那么key就成为左子节点
        如果key比currentNode大,那么_put到右子树
        但如果没有右子树,那么key就成为右子节点
        '''
        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, k, v):
        self.put(k ,v)

    def get(self, key):
        '''
        在树中找到key所在的节点取到payload
        '''
        if self.root:
            res = self._get(key, self.root)
            if res:
                return res.payloadd
            else:
                return None
        else:
            return None

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

    def __getitem__(self, key):
        '''
        实现val= myZipTree['PKU']
        '''
        return self.get(key)

    def __contains__(self, key):
        '''
        实现'PKU' in myZipTree的归属判断运算符in
        '''
        if self.__get(key, self.root):
            return True
        else:
            return False
    def __iter__(self):
        '''
        实现迭代器
        迭代器函数中用了for迭代,实际上是递归函数
        yield是对每次迭代的返回值 中序遍历的迭代
        :return:
        '''
        if self:
            if self.hasLeftChild():
                for elem in self.leftChild:
                    yield elem
            yield self.key
            if self.hasRightChild():
                for elem in self.rightChild:
                    yield elem

还有BST.delete方法,BST.remove方法 ,比较复杂,这里就不写了。主要思路是要考虑delete是左子节点还是右子节点,然后是否还有左子节点和右子节点。

 

posted @ 2020-07-29 21:21  Yelush  阅读(120)  评论(0编辑  收藏  举报