二叉查找树

1. 二叉查找树:(BST)

1.1定义:

1.若左子树非空,则左子树上的所有结点小于该结点的值;
2.若右子树非空,则右子树上的所有结点大于该结点的值;
3.任意结点的子结点都是二叉查找树;

1.2性质:

1.查找、插入、删除的时间复杂度均为O(lgn);
2.二叉查找树不保证平衡,在最坏情况下是一个链表,各种操作复杂度变为O(n);

1.3操作:

增加结点:
先执行一次查找,即可找到要插入的位置;然后插入即可;

删除结点:
1.如果删除的是叶节点,直接删除;
2.如果被删除的元素只有一个子节点,可以将子节点直接移到被删除元素的位置;
3.如果被删除的元素有两个子节点,就从右子树中找到最小的的结点,和待删除的结点互换,最后删掉该结点;


2. 平衡二叉树:(AVL)

相比于普通的二叉查找树,平衡二叉树改进的点是完全避免了在最坏情况下查找树退化为链表

2.1定义:

1.首先它是一棵二叉查找树,满足二叉查找树的所有性质;
2.任一结点的左右子树都是平衡的(左右子树高度差不大于1)

2.2性质:

1.查询的时间复杂度是 O(logN);
2.插入的时间复杂度是 O(logN),其中O(logN)的时间用于查找插入点,最多两次旋转用于插入维护平衡;
3.删除的时间复杂度是 O(logN),其中O(logN)的时间用于查找插入点,O(1)用于删除,O(KlogN)的时间用于旋转维护平衡;
3.任意结点的子结点都是平衡二叉树;

2.3操作:

旋转的规律:
1.旋转都是以深度最大的平衡因子为2的节点为基准节点;
2.旋转有单旋和双旋两中情况,一字排列的树形结构适用于单旋,之子排列的树形适用于双旋;
3.删除节点可能会使基准树的高度减1,所以可能导致多次双旋
下图是一次双旋的过程,经过一次旋转转化为一字型的情况,再通过一次单旋解决不平衡
在这里插入图片描述
新增结点:按BST的方式插入,并进行最多两次旋转,过程略 O(logN);
删除结点:按BST的方式删除,并进行最多可达树高(logN)轮旋转,复杂度也是O(logN)


3.红黑树:

相比于平衡二叉树,它的改进点在于,以适当地牺牲平衡性为代价,避免了以O(logN)时间为代价去维护树的平衡性

3.1定义:

1.结点是红或黑色;
2.根节点始终是黑色;
3.全部叶结点都是黑色;
4.红节点不能相邻;
5.从任意一个结点到每个叶节点的黑色结点数相同

3.2性质:

1.它是一棵二叉查找树,满足二叉查找树的所有性质
2.在最坏情况下,查找、插入、删除的时间复杂度能达到O(lgn);
3.从根到叶子的最长路径最多不会超过最短路径的两倍
4.任何不平衡都会在三次旋转之内解决

3.3红黑树与B树的关系:

任何一棵红黑树都可以转化为一棵(2,4)树
转化的方法是将所有红色节点提升至与黑色父节点平齐,组成一个之多含有三个关键码的超级节点,而且红黑树的插入删除操作也可以通过2-4树间接完成


3.4 AVL和红黑树比较:

1.AVL要求高度平衡,为了维持高度平衡需要旋转的的次数较多牺牲了效率;而红黑树在平衡性上做了妥协,从而换取了更高的效率;
2.红黑树的高效主要体现在删除结点的过程中,删除节点后维护平衡的时间从O(LogN)降低至O(1);
2.红黑树的查找效率略低于AVL,因为红黑树高度略高;

3.5 红黑树的用途:

TreeMap和HashMap中都用到了红黑树
TreeMap整体就是一个大的红黑树,Key值需要可以被比较,TreeMap以Key为基准中序遍历会得到一个升序的序列
HashMap是无序的,可能包含多个小的红黑树


4.伸展树

伸展树与AVL或红黑树相比,彻底放开了对平衡度的限制,但是通过伸展策略可以使树趋于平衡;

4.1 特点:

1.它是一棵二叉查找树;
2.满足局部性的特性,即被访问过的元素都会通过左右旋被提升到根节点,后续访问到这个元素附近的节点效率就会提升
3.一棵伸展树极端情况下可能是一条链表,但是随着使用过程中多次旋转,会逐渐趋于平衡

4.2 操作:

1.伸展:
查找到目标节点后执行伸展算法,需要考虑目标节点的父节点和祖父节点之间的位置关系

情况1: 如果被访问的节点与父节点及祖父节点成之字排列,就简单旋转目标节点的父节点,每次旋转目标节点就会上升一层:

		G						G						
		  \						  \						*T
		    P		->			   *T       ->        /     \
		  /                          \				 G       P
		*T                             P

情况2: 如果被访问节点与父节点及祖父节点成一字排列,就先旋转祖父节点,再旋转父节点:

	   G												  *T
		 \						  P  					  /
		   P		 ->		    /   \       ->          P
		     \                 G     *T   			  /	        
		      *T                                    G

伸展树采用了上面的伸展策略,使得伸展树在多次伸展的过程中逐渐趋于平衡
2.查找:
像普通的二叉查找树那样查找,平均耗时O(Logn),然后执行一次伸展算法,耗时O(Logn)
如果查找失败,那么在这次查找过程中访问的最后一个节点也会被伸展至树根
3.插入:
插入前首先要进行一次查找,平均耗时O(Logn),这次查找会失败,但是目标节点的父节点会被提升到树根,平均耗时O(Logn),最后把树拆分成左右两半,目标节点作为树根插入,耗时O(1)
在这里插入图片描述
4.删除:
插入前首先要进行一次查找,平均耗时O(Logn),目标节点被提升至树根,平均耗时O(Logn),然后删除树根节点,最后从右子树哪一个最小的节点放在树根,平均耗时O(Logn)
在这里插入图片描述

4.3 总结

伸展树的增删查的平均时间复杂度都是O(Logn),与AVL树相当;如果数据访问的局部性较强,伸展树的效率会比AVL更好

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值