美文网首页算法数据结构
数据结构之二叉搜索树

数据结构之二叉搜索树

作者: 人魔七七 | 来源:发表于2018-12-12 17:20 被阅读27次

基本概念

  • 二叉搜索树是由二叉树组成的,专门用于搜索和查找为目的的一种树。
  • 当前结点比其左子树的其他结点都大,相反当前结点比其右子树的其他结点都小。
  • 这个二叉搜索树和我们之前构建堆的思路很相似,参考这个链接

基本的操作

  1. 插入操作,通常这也是构建的方法。
  2. 删除操作,删除操作分几种情况。
  • 删除的结点有左右孩子
  • 删除的结点没有左右孩子
  • 删除的结点有一个左孩子
  • 删除的结点有一个右孩子
  1. 查找操作,这也是经常用的操作,删除也依赖这个操作。

插入操作

思路
  1. 如果要插入的结点比根结点小,则往左边调整,继续比较。相反如果要插入的结点比根结点大,则往右边调整。
  2. 循环的按照上述步骤走。
  3. 直到走到要对比的结点不存在右孩子或者左孩子跳出循环。
  4. 插入结束。
动画
代码
- (void)insertObject:(NSObject *)newObj
{
    //创建一个结点根据newObject
    DSTreeNode *treeNode    = [[DSTreeNode alloc] init];
    treeNode.object          = newObj;
    treeNode.compareSelector = self.root.compareSelector;
    //currentNode 和 parentNode指向根结点
    DSTreeNode *currentNode = self.root;
    DSTreeNode *parentNode  = self.root;
    
    while (YES) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        //比较当前结点和新插入结点大小
        NSComparisonResult result = (NSComparisonResult)[newObj performSelector : currentNode.compareSelector withObject : currentNode.object];
#pragma clang diagnostic pop
        //如果新结点比current指针指向的结点大
        if (result >= 0) {
            //且当前结点不存在右结点则插入 两个结点指针调整互指 然后结束循环
            if (!currentNode.rightChild) {
                currentNode.rightChild = treeNode;
                treeNode.parent        = parentNode;
                break;
            }
            //否则向下移动current 和 parentNode指针继续循环执行上面的操作
            else {
                currentNode = currentNode.rightChild;
                parentNode = currentNode;
            }
        }
        //和上面的思路类似
        else {
            if (!currentNode.leftChild) {
                currentNode.leftChild = treeNode;
                treeNode.parent       = parentNode;
                break;
            }
            else {
                currentNode = currentNode.leftChild;
                parentNode  = currentNode;
            }
        }
    }
}

查找操作

思路
  1. 从树的最顶端开始查找
  2. 如果查找的结点值小于当前位置结点向左走,反之向右走。
  3. 既不大于也不小于也就是结束,找到这个结点了。
动画
代码
//查找方法
- (DSTreeNode *)find:(NSObject *)obj
{
    //当前指针指向根结点
    DSTreeNode *currentNode = self.root;
    
    while (YES) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        //比较当前结点和查找结点
        NSComparisonResult result = (NSComparisonResult)[obj performSelector : currentNode.compareSelector withObject : currentNode.object];
#pragma clang diagnostic pop
        //如果查找结点值大于根结点说明在右子树上
        if (result > 0) {
            //当前结点存在右结点 指针下移动
            if (currentNode.rightChild) {
                currentNode = currentNode.rightChild;
            }
            else
                return nil;
        }
        //这个查找左边子树的思路和上面一样
        else if (result < 0) {
            if (currentNode.leftChild) {
                currentNode = currentNode.leftChild;
            }
            else
                return nil;
        }
        else {
            break;
        }
    }
    
    return currentNode;
}

删除操作

思路
  1. 上面已经说分几种情况了,这里说一种最复杂的情况就是这个被删除结点存在左右孩子,其他的也就好理解了,看代码注释。
  2. 删除这个结点。
  3. 找到被删除结点右子树中最小的结点替换被删除的结点,或者左子树中最大的结点替换被删除的结点。
动画
代码
//删除某个结点
- (DSTreeNode *)deleteObject:(NSObject *)obj
{
    //找到当前结点
    DSTreeNode *node = [self find:obj];
    
    if (node) {
        //如果被删除的结点存在左右孩子
        if (node.leftChild && node.rightChild) {
            //找到后继结点也就是右子树的最小结点
            //            DSTreeNode *tmpCell = node.rightChild;
            //            while (tmpCell.leftChild) {
            //                tmpCell = tmpCell.leftChild;
            //            }
            
            //找到后继结点也就是左子树的最大结点
            DSTreeNode *tmpCell = node.leftChild;
            while (tmpCell.rightChild) {
                tmpCell = tmpCell.rightChild;
            }
            //交换这两个结点指针
            NSObject *temp;
            temp            = [node.object copy];
            node.object     = [tmpCell.object copy];
            tmpCell.object  = temp;
            //删除这个被替换掉的结点
            if ([tmpCell isLeftChildOfParent]) {
                tmpCell.parent.leftChild = nil;
            }
            else {
                tmpCell.parent.rightChild = nil;
            }
        }
        //如果不存在左右孩子 又分几种情况没有左右孩子,有一个左孩子,有一个右孩子
        else {
            if (node.leftChild != nil) {
                node = node.leftChild;
            }
            else if (node.rightChild != nil) {
                node = node.rightChild;
            }
            if ([node isLeftChildOfParent]) {
                node.parent.leftChild = nil;
            }
            else {
                node.parent.rightChild = nil;
            }
        }
    }
    
    return node;
}

总结

  • 其实这些操作过程时间复杂度主要在对比查找的过程。

  • 最坏的情况下,只需要查找一个分支上的数据即可,不需要检索每个数据。因此复杂度是O(lgn),这样的情况下树是相对平衡的。

  • 如果这个数只有一个单独的右分支的情况下查找结点的复杂度就是O(n)了,其实就是从头到尾检索所有的结点。

没有对比没有伤害

看下图这个情况,这样的查找效率最低
理想的状态

下回预告

综上所述保持二叉搜索树处于平衡状态很重要,这样我们能提高查找的效率。让其平衡有一种方法就是将二叉搜索树实现为AVL树。

参考链接

https://www.jianshu.com/p/f35e700748e9
https://www.bysocket.com/?p=1209
https://github.com/raywenderlich/swift-algorithm-club/tree/master/Binary%20Search%20Tree
https://github.com/EvgenyKarkan/EKAlgorithms/tree/master/EKAlgorithms/Data%20Structures/BinarySearchTree

书籍

算法精解
算法动画图解

Demo

https://github.com/renmoqiqi/DSBSTree/tree/master

相关文章

  • Go语言数据结构和算法-BinarySearchTree(二叉搜

    Go语言数据结构和算法-BinarySearchTree(二叉搜索树) 二叉搜索树的数据结构 Insert(val...

  • 数据结构-二叉搜索树

    数据结构-二叉搜索树(BST) 定义:二叉搜索树是一个节点类的二叉树数据结构,包含以下特点: -左子树仅包含比根节...

  • 二叉树

    参考文章 百度 数据结构中有很多树的结构,其中包括二叉树、二叉搜索树、2-3树、红黑树等等。本文中对数据结构中常见...

  • Day3--搜索树

    在二叉判定树以及二分搜索的基础上,基于二叉树的搜索树产生,该数据结构可以随时进行调整,可以保证高效的搜索效率。 内...

  • 【学习】数据结构和算法

    数据结构 线性表:数组 栈 队列 链表树:二叉树 二叉树遍历 二叉搜索树 B树 红黑树 堆图:图其他:哈希表...

  • Go:实现二叉搜索树(BST)

    二叉搜索树是一种支持快速查找、增加和删除元素的数据结构。二叉搜索树中的节点是有序的,因此支持快速查找。该数据结构由...

  • 如何在Java中实现二叉搜索树

    二叉搜索树或BST是一种流行的数据结构,用于保持元素的顺序。二叉搜索树是二叉树,其中左子节点的值小于或等于父节点,...

  • 二叉排序树

    注 关于二叉搜索树更为详细的解释请详看 《大话数据结构》第八章 查找 中二叉搜索树这一小节 二叉排序树(Binar...

  • 彻底理解红黑树(一)之二叉搜索树

    彻底理解红黑树(一)之二叉搜索树彻底理解红黑树(二)之插入彻底理解红黑树(三)之删除 1. 二叉搜索树的定义 二叉...

  • 图解“红黑树”原理,一看就明白

    学过数据结构都知道二叉树的概念,而又有多种比较常见的二叉树类型,比如完全二叉树、满二叉树、二叉搜索树、均衡二叉树、...

网友评论

    本文标题:数据结构之二叉搜索树

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