二叉搜索树

二叉搜索树是一个链式结构的,快速的进行数据的查询,删除,插入操作的数据结构(lg(n)的时间复杂度)

然而,上面这些所有的功能利用数组+类似快排的操作也能完成,为什么要用跟麻烦的二叉搜索树呢

数组,是一开始就要开好的在内存中占用了一段连续的内存,如果一个程序,他平时的数据流量比较小,用数组的话就必须开到最大流量时的内存

而我们的二叉搜索树是链式存储,并不需要连续的内存,这样就节省了程序运行时的内存消耗

 

性质:

  一个点的所有左子树的值都比这个节点的值小,所有右子树的值都比这个节点的值大

  如果有特殊的需求(会出现两个相同的值)我们可以考虑让左子树的值都<=这个节点的值

操作:

  插入:

    对于如果已有一颗二叉搜索树,我要把值x插入这棵二叉树中

    我们只需要从根节点开始比较,如果x < root则往左子树上插否则则往右子树上插

    直到我们发现我们要插的子树为空,那么把x放在这里就好了

    这个东西用递归实现

  查询:

    我要在树中查询值为x的节点,我们将x与根节点比较,如果 x < root就在左子树中找否则就在右子树中找

    当root == x时root就是要找的节点

  删除:

    假设要删除x节点

    x为叶子节点:直接删掉就好了

    x只有左子树或只有右子树:

      在网上看这个的时候感觉好多博客都没完全说清楚,我来一个详细的解释

      只有左子树:

        直接把这个节点删掉,然后把他的左子树(x_left)与原来连接原来连接这个节点的线连接到一起就行了

        那么如果原来x是fa_x的右子树,fa_x的右子树就是x_left

        因为x下的所有节点都>fa_x  所有x_left做fa_x的右子树是完全没有问题的

        是fa_x的左子树同理

      只有右子树同理

    x既有左子树又有右子树:

      这时我们在删掉x后要在右子树中找一个来替换x的位置

      要保证x的性质的话,我们只需要找到右子树中最小的(repl_x)那个即可

      因为repl_x > x左边所有的数而小于x右边所有的树

      把repl_x换过去之后,repl_x就空出来了对吧

      因为repl_x是右子树中最小的,那么他肯定没有左子树,这就是删除节点的前两中种情况了,按前两种情况删除repl_x即可

 

  总结:

    虽然说二叉搜索树的时间复杂度是(lg(n))但是从操作中可以看出来,我们的时间复杂度实际是O(tree_h)

    如果我插入这棵树的时候是按数值顺序插入的,那么这棵树就会退化成一个链表,时间复杂度退化成O(n)

    

    如果有人问,我们已经知道数值了,为什么还要查询这些东西?

    那么数值可以理解为主建或者说用户名

    跟这个主建所绑定的有其他的东西,比如年龄,学号之类的个人资料,这就是二叉搜索树的实际应用

    这也应该是为什么我们要保证玩游戏时用户名不能重复的原因,如果用户名重复。。。。查询个人信息的时候是返回哪个呢?

 

  代码:(下午再写,啦啦啦~)

 

posted @ 2017-12-21 10:27  shensobaolibin  阅读(183)  评论(0编辑  收藏  举报