眩しさだけは、忘れなかった。|

【数据结构-查找】树型查找

1 折半查找判定树

1.1 折半查找判定树的性质

  1. 若指针 low 和 high 指向表的上界和下界,mid = (low+high)/2(向下取整,也是 C 语言除法运算的特性),则:
  • 若 low 和 high 之间有奇数个元素,则 mid 的左右部分元素个数相等;
  • 若 low 和 high 之间有偶数个元素,则 mid 的左半部分比右半部分元素个数少一个。

【例】若 low 和 high 之间有 10 个元素,则 mid = (low+high)/2 = (1+10)/2 = 11/2 = 5,所以 mid 的左半部分有 4 个元素,右半部分有 5 个元素。

  1. 若指针 low 和 high 指向表的上界和下界,mid = (low+high)/2(向上取整,或按照 C 语言规则写成 (low+high)/2+1),则:
  • 若 low 和 high 之间有奇数个元素,则 mid 的左右部分元素个数相等;
  • 若 low 和 high 之间有偶数个元素,则 mid 的左半部分比右半部分元素个数多一个。

【例】若 low 和 high 之间有 10 个元素,则 mid = (low+high)/2 + 1 = (1+10)/2 + 1 = 11/2 + 1 = 6,所以 mid 的左半部分有 5 个元素,右半部分有 4 个元素。

【推论】在分块查找中,若对索引表进行向下取整的折半查找时,若索引表不包含目标关键字,则折半查找最终停在 low > high,要在 low 所指的分块查找;若对索引表进行向上取整的折半查找时,若索引表不包含目标关键字,则要在 high 所指的分块查找。

  1. 任意两棵折半查找判定树,若取整方向一致,且它们的结点个数相同,则它们的结构完全相同。

【注】在 1.2 节判定树的画法中将体会到这一点。

  1. 若折半查找判定树有 n 个结点,则失败结点(外部结点/空指针域)有 n+1 个。

【证明】判定树是一棵有 n 个结点的非空二叉树,设不同度的结点个数分别为 n0、n1、n2,有n0 = n2 + 1n = n0 + n1 + n2,将n2代入消去,得n = 2n0 + n1 - 1。注意到此时2n0 + n1即为空指针域的总数,因而总结点数比空指针域总数少 1。

  1. 若折半查找判定树有 n 个结点,则树高(不包含失败结点)为log2(n+1)(向上取整)log2n(向下取整)+1,即查找成功最多需要log2(n+1)(向上取整)次,时间复杂度为 O(log2n)。

1.2 折半查找判定树的画法

向下取整的折半判定树的画法:

  • 先画出最大的满二叉树;
  • 从上往下看,比较每个结点的左右子树的结点个数,若个数相同则优先放右边,若左边比右边少则放左边。

向上取整的折半判定树的画法:

  • 先画出最大的满二叉树;
  • 从上往下看,比较每个结点的左右子树的结点个数,若个数相同则优先放左边,若右边比左边少则放右边。

【例】画出一棵共 12 个结点的查找判定树(向下取整):

image

1.3 折半查找法的查找长度

  • 通用公式:ASL = ∑(查找次数*概率)
  • 查找成功公式:ASL(成功) = ∑(查找成功次数*概率),其中概率 = 1/成功结点总数
  • 查找失败公式:ASL(成功) = ∑(查找失败次数*概率),其中概率 = 1/失败结点总数

以上图为例:

  • ASL(查找成功)= 1*1/12 + 2*2/12 + 3*4/12 + 4*5/12 = 37/12
  • ASL(查找失败)= 3*3/13 + 4*10/13 = 49/13

1.4 相关例题

关键字:6,8,10,13,19,21,28,32,36,40,45

image

2 二叉排序树(BST)

2.1 二叉排序树的性质

  1. 若二叉排序树有 n 个结点,则树高(不包含失败结点)为log2(n+1)(向上取整)log2n(向下取整)+1,即查找成功最多需要log2(n+1)(向上取整)次,时间复杂度为 O(log2n)。插入和删除操作的时间复杂度需要 O(n)。

  2. 在二叉排序树中删除并插入某结点,得到的排序二叉树一般与原来不同。

  3. 折半查找判定树唯一,但二叉排序树不唯一,其结构与关键字的插入顺序有关。

  4. 假设以 nh 表示深度为 h 的二叉平衡树中含有的最少结点数(可得到最大深度的二叉平衡树),则有 n0 = 0,n1 = 1,n2 = 2,并且nh = nh-1 + nh-2 + 1

2.2 二叉排序树的建立(代码)

#include <cstdio>
using namespace std;

// 二叉树结点声明 
typedef struct TreeNode{
	TreeNode *left;
	TreeNode *right;
	int data;
	TreeNode (int x): left(NULL), right(NULL), data(x) {}
} TreeNode;

// 二叉排序树的建立 
TreeNode *insert (int x, TreeNode *root){
	if (root == NULL){
		root = new TreeNode(x);
	}
	else if (x < root->data){
		root->left = insert(x, root->left);
	}
	else{
		root->right = insert(x, root->right);
	}
	return root;
}

// 前序遍历 
void PreOrder (TreeNode *root){
	if (root != NULL){
		printf("%d ", root->data);
		PreOrder(root->left);
		PreOrder(root->right);
	}
}

// 中序遍历 
void InOrder (TreeNode *root){
	if (root != NULL){
		InOrder(root->left);
		printf("%d ", root->data);
		InOrder(root->right);
	}
}

// 后序遍历 
void PostOrder (TreeNode *root){
	if (root != NULL){
		PostOrder(root->left);
		PostOrder(root->right);
		printf("%d ", root->data);
	}
}

int main(){
	int n;
	TreeNode *T;
	
	while (scanf("%d", &n) != EOF){
		T = NULL;
		for (int i = 0; i < n; i++){
			int x;
			scanf("%d", &x);
			T = insert(x, T);
		}
		PreOrder(T); printf("\n");
		InOrder(T); printf("\n");
		PostOrder(T); printf("\n");
	}
	
	return 0;
}

2.3 二叉排序树的插入和删除

image

image

删除操作:可先将元素按序排列,然后找到待删除元素的左右两个元素,挑选任意一个元素替代这个待删除元素即可。

如上图:元素排好序后为 1,2,3,5,6,7,8,10,11,12,则删除元素 2,可选择元素 1 去替代它(法二),也可以选择元素 3 去替代它(法一)。

3 平衡二叉树(AVL)

3.1 平衡二叉树的性质

  • 任何一个结点的左右两个子树的高度之差不超过 1,并且左右两个子树都是一棵平衡二叉树。
  • 查找、插入和删除操作的时间复杂度需要 O(log2n)。

3.2 平衡二叉树的旋转

3.2.1 基本操作——左旋、右旋

image

  • 左旋:不平衡结点变为其右孩子的左孩子。
  • 右旋:不平衡结点变为其左孩子的右孩子。

3.2.2 四种非平衡形态——LL、RR、LR、RL

image

  • LL 型:结点 A 的左孩子(L)的左子树(L)插入了新结点,导致结点 A 失衡。解决办法:右旋一次。
  • RR 型:结点 A 的右孩子(R)的右子树(R)插入了新结点,导致结点 A 失衡。解决办法:左旋一次。
  • LR 型:结点 A 的左孩子(L)的右子树(R)插入了新结点,导致结点 A 失衡。解决办法:左旋一次,转化为 LL 型,再右旋一次。
  • RL 型:结点 A 的右孩子(R)的左子树(L)插入了新结点,导致结点 A 失衡。解决办法:右旋一次,转化为 RR 型,再左旋一次。
【应试】简化流程

因为实际的二叉树形态很复杂,因此需要一个简便的方法用来快速解题(例子见下节):

  • 从最深的叶结点一路向上找到第一个失衡结点;
  • 从这条路径上的失衡结点以及后面两个结点,组成了四种非平衡形态的一种;
  • 先断开其他结点,把这三个结点按上面四种形态旋转,使其恢复平衡;
  • 最后把断开的其他结点按照关系连回到正确位置上。

3.3 平衡二叉树的插入

【例 1】插入序列 {15,3,7,10,9,8}

image

【例 2】插入序列 {1,2,3,4,5,6,7}

image

【例 3】插入序列 {2,1,5,3,8,9,10,11,4,7,6}

image

image

4 多路平衡查找树(B 树)

4.1 B 树的性质

假设一棵 m 阶 B 树,则满足以下特性:

  1. 每个结点最多有 m 棵子树,最多含有 m-1 个关键字。

  2. 根结点(如果它不是终端结点)至少有两棵子树。

  3. 所有非叶结点(根结点除外)最少有m/2棵子树(即最少有 m 的一半过数这么多),最少含m/2-1个关键字。

【推论】结点的关键字个数范围为m/2-1 ≤ n ≤ m-1

  1. 设 B 树有 n 个关键字,则其高度范围为logm(n+1) ≤ h ≤ log┍m/2┑((n+1)/2) + 1

【证明 1】结点最多(且每个结点含关键字数最多,高度最小)的情况:B 树每个结点最多有 m 棵子树、m-1 个关键字,所以关键字总数的范围为n ≤ (m-1)(1+m+m2+...+mh-1) = mh-1,反解出 h 的范围:logm(n+1) ≤ h

【证明 2】结点最少(且每个结点含关键字数最少,高度最大)的情况:设k = m/2,B 树每个结点最少有 k 棵子树、k-1 个关键字。第 1 层最少有 1 个结点,第 2 层至少有 2 个结点,第 3 层至少有 2k 个结点,第 4 层至少有 2k2 个结点,以此类推,第 h 层至少有 2kh-2 个结点;因而,第 1 层最少有 1 个关键字,第 2 层至少有 2(k-1) 个关键字,第 3 层至少有 2k(k-1) 个关键字,第 4 层至少有 2k2(k-1) 个关键字,以此类推,第 h 层至少有 2kh-2(k-1) 个关键字。所以,关键字总数的范围为n ≥ 1 + 2(k-1) + 2k(k-1) + 2k2(k-1) + ... + 2kh-2(k-1) = 1 + (k-1)(1 + k + k2 + ... + kh-2) = 1 + 2(kh-1 - 1),反解出 h 的范围:h ≤ logk((n+1)/2) + 1 = log┍m/2┑((n+1)/2) + 1

  1. B+ 树可视为使用了分块查找的 B 树。

相关例题

【例 1】高度为 5 的 5 阶 B 树至少有几个结点和关键字?至多有几个结点和关键字?

【解】a. 结点最少的情况:根结点有 2 棵子树,其他非叶结点有 3 棵子树,设高度为 h,则结点总数为1 + 2 + 2*31 + 2*32 +...+ 2*3h-2 = 1 + 2 * (30 + 31 +...+ 3h-2) = 1 + 2 * 1/2 * (3h-1 - 1) = 3h-1,代入 h=5 得结点总数为 81。

b. 关键字最少的情况:在结点总数最少的情况下,根结点有 1 个关键字,其他非叶结点有 2 个关键字,设高度为 h,则关键字总数为1 + 2 * (2 + 2*31 + 2*32 +...+ 2*3h-2) = 1 + 4 * (30 + 31 +...+ 3h-2) = 1 + 4 * 1/2 * (3h-1 - 1) = 1 + 2 * (3h-1 - 1),代入 h=5 得关键字总数为 161。

c. 结点最多的情况:所有结点都有 5 棵子树,设高度为 h,则结点总数为1 + 5 + 52 + 53 +...+ 5h-1 = 1/4 * (5h - 1),代入 h=5 得结点总数为 781。

d. 关键字最多的情况:在结点总数最多的情况下,根结点和其他非叶结点有 4 个关键字,设高度为 h,则关键字总数为4 * (1 + 5 + 52 + 53 +...+ 5h-1) = 5h - 1,代入 h=5 得关键字总数为 3124。

【例 2】一棵 3 阶 B 树中有 2047 个关键字,则此 B 树的最大高度是多少?最小高度是多少?

【解】a. 最大高度:即结点总数和关键字总数都是最少的情况,根结点有 2 棵子树(1 个关键字),其他非叶结点有 2 棵子树(1 个关键字)。则关键字总数为1 * (1 + 2 + 22 + 23 +...+ 2h-1) = 2h - 1 = 2047,解得 h=11。

b. 最小高度:即结点总数和关键字总数都是最多的情况,所有结点都有 3 棵子树(2 个关键字)。则关键字总数为2 * (1 + 3 + 32 + 33 +...+ 3h-1) = 2 * (3h - 1) = 2047,解得 h=7。

【例 3(变形)】在一棵有 15 个关键字的 4 阶 B 树中,含关键字的结点个数最多几个?

【解】因为题目所求的是最多的结点数量,所以在关键字总数一定(15 个)的情况下,让每个结点都存储最少的关键字数。即根结点有 1 个关键字,其他非叶结点有 1 个关键字,推出每个非叶结点有 2 棵子树。因此关键字总数为1 * (1 + 2 + 22 + 23 +...+ 2h-1) = 1 * (2h - 1) = 2h - 1 = 15,解得 h=4。易知,含关键字的结点有 15 个。

【例 4(变形)】在一棵高度为 2 的 5 阶 B 树中,所含关键字的个数至少几个?

【解】因为题目所求的是最少的关键字总数,所以在高度一定的情况下,要求结点数最少,且每个结点所含关键字尽可能的少。因此,根结点有 1 个关键字,2 棵子树;其他非叶结点有 2 个关键字。因为高度为 2,所以第一层是根结点,第二层是两个非叶结点,关键字总数为 1+2*2=5。

4.2 B 树的插入和删除

image

image

相关例题

一棵 3 阶 B 树,插入 90、插入 25、插入 45、删除 60、删除 80:

image

image

5 红黑树

(略)

---EOF---

本文作者:漫舞八月(Mount256)

本文链接:https://www.cnblogs.com/Mount256/p/16571151.html

版权声明:本作品采用CC 4.0 BY-SA许可协议进行许可。

posted @   漫舞八月(Mount256)  阅读(468)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开
  1. 1 Main Menu Theme Syd Matters
  2. 2 Luminous Memory (Acyanxi Remix) Acyanxi
  3. 3 夏影 麻枝准
  4. 4 潮騒の香り 水月陵
  5. 5 stand still 井口裕香 (いぐち ゆか)
  6. 6 流星雨 麻枝准
  7. 7 Summer Fantasy 傅许
  8. 8 失う 米白
  9. 9 epilogue 霜月はるか
  10. 10 夏に君を待ちながら 小原好美
  11. 11 桜のような恋でした 鹿乃 (かの)
  12. 12 風は微かに、熱を残し… 水月陵
  13. 13 夏凪ぎ 麻枝准/やなぎなぎ
  14. 14 空に光る 戸越まごめ
  15. 15 木漏れ日 riya
  16. 16 Songbirds Homecomings (ホームカミングス)
  17. 17 宝物になった日 麻枝准/やなぎなぎ
  18. 18 夏影~あの飛行機雲を超えた、その先へ~ 雪桜草 (雪樱草)
  19. 19 快晴 Orangestar (蜜柑星P),初音未来 (初音ミク)
  20. 20 永遠 霜月はるか
  21. 21 Sion 天門
  22. 22 遙かな年月-piano- 麻枝准
  23. 23 夏恋慕 kobasolo/春茶
  24. 24 夏凪ぎ-piano ver.- MANYO/麻枝准
  25. 25 Goodbye Seven Seas -piano ver.- MANYO/麻枝准
  26. 26 Light Years 麻枝准/やなぎなぎ
  27. 27 優しさの記憶 鹿乃 (かの)
夏凪ぎ - 麻枝准/やなぎなぎ
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 麻枝准

作曲 : 麻枝准

编曲 : MANYO

编曲:MANYO

演唱:nagi

日差しが眩しくて

一瞬目を閉じた

そのまま眠ってた

遙かな旅をして

同じ海を見たい

それは贅沢かな

賑やかな日常は過ぎ去り

梅雨も軒をくぐって

もうすぐ新しい季節ヘと

向かうけどきみはどこで

笑ってる泣いてるんだ 叫ぶけど

届かない まだあの夏に居るんだ

きみがいいきみがいいって

願うけど

神様 そんなの今更だよね

遠くへ 遠くへ

遠くへ 遠くへ

星を追い越し花火が

次から次ヘと咲いた

それももう遠い記憶

時は流れ今も

笑ってたい泣いてたいよ

きみのため

大事にすくっても溢れ零れる

痛いほど締めつけられてもなお

わずかな光を頼りに進む

雨さえ冷たくて凍えそう

足すら止めてしまいそうでも

今だけ出来るだけ笑って生きる

きみから教えてもらったことだ

笑ってる泣いてるきみと生きる

笑ってよ泣いていいんだよ

もっと僕に

目指そう あの夏ヘと続く道

神様 奇跡は僕らが起こす

日差しが眩しくて

一瞬目を閉じた

隣にきみが居た

End