Lauen_1

Stay foolish

关于查找

     介绍二分查找,二叉查找树(结合链表和二分查找的特性),平衡二叉查找树(AVL树,2-3树,红黑树),B树等。

  1. 二分查找

    二分查找是针对有序数组的,但是二分查找的插入比较慢,在插入比较多的情况并不适用。 

  2. 二叉查找树

    结合二分查找与链表的特点,设计出了二叉查找树,如下图所示

    在二叉查找树中,左子树的关键字不大于其父节点的关键字,右子树的关键字不小于其父节点。

    由于二叉查找树可能出现一些不平衡的现象,这样会导致插入和查找的时间复杂度变得和顺序查找一样。

    所以出现了一些自平衡的二叉查找树以及伸展树(spaly)来避免这种问题详见下一小节介绍

    另外关于二叉搜索树的删除操作,相对比较复杂,主要有三种情况,1.没有孩子;2.有一个孩子;3.有两个孩子。

    当有两个孩子时,需要找到该节点的后续,或者说是右孩子中的最小的值。如图删除节点37.

    三种删除情况的示例。

     

  3. 自平衡二叉搜索树

    AVL树,它是一种自平衡的二叉查找树,对每一个结点,它的左右子树高度至多差1。要实现AVL数,需要在节点内维护一个记录高度的域。

    在插入操作失去平衡时,利用旋转来重新保持平衡。下图为wikipedia的图,竖方向看如何平衡,主要有四种情况

    Splay树是一种自调整树,伸展树并没有AVL的平衡要求,任意节点的左右子树可以相差任意深度。

    与二叉搜索树类似,伸展树的单次搜索也可能需要n次操作。但伸展树可以保证,m次的连续搜索操作的复杂度为mlog(n)的量级,而不是mn量级。它通过在查询到目标节点后,会不断进行下面三种操作中的一个,直到目标节点成为根节点。伸展树的另一个好处是将最近搜索的节点放在最容易搜索的根节点的位置。在许多应用环境中,比如网络应用中,某些固定内容热点内容会被大量重复访问。伸展树可以让这种重复搜索以很高的效率完成。主要有三种旋转的情况:

    1. Zig or Zag

    2. Zig-Zig and Zag-Zag

    3. Zig-Zag

 

2-3树,它是二叉树的一种拓展,允许一个节点保持多个键即为3-结点,它有两个键,三条链接。2-结点与二叉查找树一样。并且为了保持平衡性,有一个限制,所有空链接到根结点的距离相等。如图所示。

关于2-3树,在插入中保持平衡性需要处理的情况比较多,所产生的开销可能比二叉查找树好不到哪里去,所以出现了红黑树,减少维护代价。

如上图所示,红链接将两个2-结点连接起来构成一个3-节点。黑链接则是2-3树中的普通链接。3-结点表示为一条向左边的红链接。所以红链接均为左链接。没有任何一个结点同时连接两个红链接。任何空节点到根节点的黑色链接的数量相同。如果指向某结点的链接是红色的,则设置该节点为红。在算法导论中,红黑树有另外一种定义:1.每个结点或是红的或是黑的。2.根节点是黑的。3.每个叶子结点是黑的。4.如果一个节点是红的,那他的两个儿子是黑的。5.对于每一个结点,从该结点到其子孙结点的所有路径上所包含数目相同的黑节点。红黑树通过简单的左旋和右旋保持其性质。插入和删除略。红黑树各类操作中,插入和删除于一般的二叉树差异比较大,而其他的操作与二叉查找树几乎没有什么大的差异,可以继续使用,并且它的操作并不涉及颜色。

 

平衡二叉树总结

红黑树的插入效率比AVL树高,因为rebalance操作时O(1),而AVL树是O(lgn),所以在频繁插入的情况下,使用红黑树比较好一些。不过search的效率比AVL略慢一些。C++中Multimap是使用红黑树实现的。因为容器有序,且查找和删除的时间复杂度均在对数级别。伸展树的另一个好处是将最近搜索的节点放在最容易搜索的根节点的位置。某些固定内容热点内容会被大量重复访问。伸展树可以让这种重复搜索以很高的效率完成。 

PS

Mark Allan Weiss的《数据结构与算法分析C++描述》中描述 "确定性跳跃表"*(determistic skiplist)一节说"性能似乎比RB-tree要强",还有省内存。

 

 

 

posted on 2015-10-25 20:47  Lauen_1  阅读(245)  评论(0编辑  收藏  举报

导航