python数据结构学习笔记-2016-12-04-02-二叉搜索树

        14.1 二叉搜索树

        二叉搜索树(binaey search tree, BST)是一种二叉树,其内的每一个结点储存着搜索关键码以及相应的负载,此二叉树以如下形式构建:

  • 对于每一个内结点,小于该内结点的关键码位于该结点的左子树内;
  • 对于每一个内结点,大于该内结点的关键码位于该结点的右子树内。
        注意二叉搜索树是不能含有重复元素的。

       14.1.1 搜索
       如果二叉搜索树内存在目标元素,那么肯定存在唯一路径从根结点到存有目标元素的结点。对于任意一处子树,我们可以将目标元素与根结点储存的元素比较,如果小于,那么就进入左子树搜索,如果大于,就进入右子树搜索。

         如果目标元素不在二叉搜索树内,那么按如上方法搜索的话,最终会碰到null子链。

       14.1.2 最大最小值
       以最小值为例,在二叉搜索树中,只需尽量向左子树移动即可。终止结点将会是叶结点或者没有左子结点的内结点。

        14.1.3 插入
        我们以构建[60, 25, 100, 35, 17, 80]的二叉搜索树为例,每一次只插入一个元素。

         可以看到,每一个新插入的元素都是在正确的位置,以叶结点形式存在。
         首先要找到正确的插入位置,我们可以使用前面提到过的搜索操作,以插入35为例:

               如上图所示,先是搜索插入位置,直到subtree为Null,之后创建新结点,开始递归回调,直至根结点。
         如果是插入已有元素,则直接返回subtree。

        14.1.4 删除元素
        删除元素较为复杂,先是进行搜索给定关键码,然后再将相应结点删除,分三种情况:
  • 删除叶结点;
  • 删除只有一个子结点的内结点;
  • 删除有两个子结点的内结点。
        删除叶结点
        这种情况最简单,在搜索到相应结点后,直接将结点分离出二叉搜索树即可。


       删除只有一个子结点的内结点

       这种情况也相对简单,只需先将该内结点分离出二叉搜索树,然后将其子结点与其父结点相连即可。


         删除有两个子结点的内结点

         这种情况最复杂,二叉搜索树如果按照中序遍历,会得到一个已排序的序列。那么对于每一个结点来说,就会有逻辑前驱(logical predecessor)和逻辑后继(logical successor),即序列中排在该结点储存元素之前的元素和之后的元素。

         对于要删除含两个子结点的内结点,首先是要搜索出该内结点的逻辑后继,然后将逻辑后继复制到该内结点上,再将逻辑后继结点删除即可。


         搜索内结点的逻辑后继,按照搜索二叉树的定义,即逻辑后继应该就在该内结点的父结点或者右子树中。


        14.1.5 二叉搜索树的效率

         假设二叉搜索树有n个结点。

        进行搜索操作时,从根结点出发,直到遇到目标结点或是Null,此时一条路径便形成。我们只需考虑最长路径即可,显然路径与二叉搜索树的高度与形状有关,最坏情况就是当二叉搜索树的高度是n时,所以其时间复杂度是O(n)。最大值和最小值搜索的时间复杂度也是O(n)。

        由于后面的添加结点或是删除结点均需用到搜索,所以这两个操作的时间复杂度也是O(n)。


        14.2 二叉搜索树的迭代器

        二叉搜索树的遍历,可先将二叉搜索树中的元素组成一个数组或是栈(使用栈更好,无需额外的内存)。

#-*-coding: utf-8-*-

# 使用二叉搜索树来实现映射ADT

class BSTMap(object):
    def __init__(self):
        self._root = None
        self._size = 0

    # 键值对数目
    def __len__(self):
        return self._size

    # 迭代器
    def __iter__(self):
        return _BSTMapIterator(self._root)

    # 判断给定关键码是否存在映射中
    def __contain__(self, key):
        return self._bstSearch(self._root, key) is not None

    # 返回给定关键码对应的值
    def valueOf(self, key):
        node = self._bstSearch(self._root, key)
        assert node is not None, "Invalid map key."
        return node.value

    # 辅助方法,在二叉搜索树中对目标元素进行搜索
    def _bstSearch(self, subtree, target):
        if subtree is None: # 终止条件
            return
        elif target < subtree.key:
            return self._bstSearch(subtree.left, target)
        elif target > subtree.key:
            return self._bstSearch(subtree.right, target)
        else: # 终止条件
            return subtree
  
    # 最小值
    def _bstMinumum(self, subtree):
        if subtree is None:
            return
        elif subtree.left is None:
            return subtree
        else:
            return self._bstMinumum(subtree.left)

    # 最大值
    def _bstMaxmum(self, subtree):
        if subtree is None:
            return
        elif subtree.right is None:
            return subtree
        else:
            return self._bstMaxmum(subtree.right)

    # 向映射中添加新的键值对
    def add(self, key, value):
        node = self._bstSearch(key) # 判断键是否已存在
        if node is not None: # 若存在,直接修改相应值
            node.value = value
            return False
        else: # 若不存在,则向二叉搜索树中插入新元素
            self._root = self._bstInsert(self._root, key, value)
            self._size += 1
            return True

    # 辅助方法,向二叉搜索树中插入新元素
    def _bstInsert(self, subtree, key, value):
        if subtree is None:
            subtree = _BSTMapNode(key, value)
        elif key < subtree.key:
            subtree.left = self._bstInsert(subtree.left, key, value)
        elif key > subtree.key:
            subtree.right = self._bstInsert(subtree.right, key, value)
        return subtree

    # 删除键值对
    def remove(self, key):
        assert key in self, "Invalid map key."
        self._root = self._bstRemove(self._root, key)
        self._size -= 1

    # 辅助方法,从二叉搜索树中删除结点
    def _bstRemove(self, subtree, target):
        # 搜索目标结点
        if subtree is None:
            return subtree
        elif target < subtree.key:
            subtree.left = self._bstRemove(subtree.left, target)
            return subtree
        elif target > subtree.key:
            subtree.right = self._bstRemove(subtree.right, target)
            return subtree
        else:
            if subtree.left is None and subtree.right is None: # 删除的结点是叶结点
                return
            elif subtree.left is None or subtree.right is None: # 删除的结点是只有一个子结点的内结点
                if subtree.left is not None:
                    return subtree.left
                else:
                    return subtree.right
            else: # 删除的结点是有两个子节点的内结点
                successor = self._bstMinumum(subtree.right) # 搜索目标结点的逻辑后继
                subtree.key = successor.key # 逻辑后继替代目标结点
                subtree.value = successor.value
                subtree.right = self._bstRemove(subtree.right, successor.key) # 删除原逻辑后继
                return subtree
        
# 二叉搜索树的迭代器,使用数组
# class _BSTMapIterator(object):
    # def __init__(self, root, size):
        # self._theKeys = Array(size)
        # self._curItem = 0
        # self._bstTraversal(root)
        # self._curItem = 0
    
    # def __iter__(self):
        # return self

    # def next(self):
        # if self._curItem < len(self._theKeys):
            # key = self._theKeys[self._curItem]
            # self._curItem += 1
        # else:
            # raise StopIteration

    # 对二叉搜索树进行中序遍历,以构建序列数组
    # def _bstTraversal(self, subtree):
        # if subtree is not None:
            # self._bstTraversal(subtree.left)
            # self._theKeys[self._curItem] = subtree.key
            # self._curItem += 1
            # self._bstTraversal(subtree.right)

# 二叉搜索树的迭代器,使用栈
class _BSTMapIterator(object):
    def __init__(self, root):
        self._theStack = Stack()
        self._traverseToMinNode(root) # 将二叉搜索树的元素压入栈中,此时不是所有元素已压入栈中

    def __iter__(self):
        return self

    def next(self):
        if self._theStack.isEmpty():
            raise StopIteration
        else:
            node = self._theStack.pop()
            key = node.key
            if node.right is not None: # 将该结点的逻辑后继压入栈中
                self._traverseToMinNode(node.right)

    # 对二叉搜索树进行遍历,直到找到其最小值为止,期间的元素压入栈中
    def _traverseToMinNode(self, subtree):
        if subtree is not None:
            subtree._theStack.push(subtree)
            subtree._traverseToMinNode(subtree.left)

# 二叉搜索树的储存类
class _BSTMapNode(object):
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.left = None
        self.right = right

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值