注:该篇文章会与我的个人博客同步更新。欢迎移步https://cqh-i.github.io/体验更好的阅读效果。
要求
- 数列有序
- 数列使用顺序存储结构
比较次数
最大比较次数介于1和 [ log 2 n ] + 1 [\log_2 n ] + 1 [log2n]+1( n为元素的个数)之间, 这点将它转换为一棵二叉树很容易看出.
题目
假设在有序线性表A[1…30]上进行二分查找,则比较五次查找成功的结点数为( )
A. 8
B. 12
C. 15
D. 16
ps:求出中间数之后, 看它是否在set集合中(set集合保存每次比较找到的数),如果不存在继续进行二分, 否则,说明这个mid之前已经查找成功过的, 那么就不用加入二分的过程了,避免重复, 这道题也可以通过找规律得出答案.
public class Erfen {
public static int sum = 0;
public static void erfen(int head, int tail, int n, Set<Integer> hadFindNumSet) {
if (n <= 0)
return;
int mid = (head + tail) / 2;
if (n == 1 && !hadFindNumSet.contains(mid)) {
hadFindNumSet.add(mid);
System.out.print("[" + head + "," + tail + "] ");
System.out.print(mid + ", ");
sum++;
}
erfen(head, mid, n - 1, hadFindNumSet);
erfen(mid + 1, tail, n - 1, hadFindNumSet);
}
public static void main(String[] args) {
int head = 1;
int tail = 30;
Set<Integer> hadFindNumSet = new HashSet<Integer>();
for (int n = 1; n <= 5; n++) {
sum = 0;
System.out.print("比较" + n + "次查找成功的点为: ");
erfen(head, tail, n, hadFindNumSet);
System.out.println(" 共有" + sum + "个");
}
}
}
运行结果:
比较1次查找成功的点为: [1,30] 15, 共有1个
比较2次查找成功的点为: [1,15] 8, [16,30] 23, 共有2个
比较3次查找成功的点为: [1,8] 4, [9,15] 12, [16,23] 19, [24,30] 27, 共有4个
比较4次查找成功的点为: [1,4] 2, [5,8] 6, [9,12] 10, [13,15] 14, [16,19] 17, [20,23] 21, [24,27] 25, [28,30] 29, 共有8个
比较5次查找成功的点为: [1,2] 1, [3,4] 3, [5,6] 5, [7,8] 7, [9,10] 9, [11,12] 11, [13,14] 13, [16,17] 16, [18,19] 18, [20,21] 20, [22,23] 22, [24,25] 24, [26,27] 26, [28,29] 28, [30,30] 30, 共有15个
生成二叉树如下图:
按规律:
二分查找的次数为
[
log
2
n
]
+
1
[\log_2 n ] + 1
[log2n]+1,最多查找5次的话,那么N最大可以是31.
31个数经过5次查找成功的节点数为
2
(
5
−
1
)
=
16
2^{(5-1)}=16
2(5−1)=16
30个数经过5次查找成功的节点数为
2
(
5
−
1
)
−
1
=
15
2^{(5-1)}-1=15
2(5−1)−1=15
…
看上面的二叉搜索树就明白了,就是第5层节点的数量.