- 折半查找:每次将待查记录所在区间缩小一半。
- 具体查找过程: 在一个非递减的有序表中,查找值为21的元素。

1.在表的两端设置两个指针high和low,

2.计算中间位置:mid=(low+high)/2。若关键字的值小于中间位置的值,则在前半区找。即,key<mid,则:high=mid+1。

3.再计算中间位置:mid=(low+high)/2。若关键字的值大于中间位置的值,则在后半区找。即,key>mid,则:low=mid+1。

4.再计算中间位置:mid=(low+high)/2。若关键字的值等于中间位置的值,则说明找到。即,key==mid,则:找到。

若表中没有元素等于key,例如上表中若查找值为63的元素,重复上述步骤,直到high<low时,结束,此时说明未找到。

-
算法步骤(非递归)
- 设表长为n,low、high和mid分别指向待查元素所在区间的上界、下界和中点,key为给定的要查找的值:
- 初始时,令low=1,high=n,mid=(low+high)/2
- 让k与mid指向的记录比较
- 若key==R[mid].key,查找成功
- 若key<R[mid].key,则high=mid-1
- 若key>R[mid].key,则low=mid+1
- 重复上述操作,直至low>high时,查找失败。
-
算法描述——非递归实现
int Search_Bin(SSTable ST, KeyType key)
{
low = 1; //置区间初值
high = ST.length;
while (low<=high)
{
mid = (low + high) / 2;
if (ST.R[mid].key == key) //直到待查元素
return mid;
else if (key < ST.R[mid].key) //缩小查找区间
high = mid - 1; //继续在前半区间进行查找
else
low = mid + 1; //继续在后半区间进行查找
}
return 0; //顺序表中不存在待查元素,返回0
}
- 算法描述——递归实现
int Search_Bin(SSTable ST, KeyType key, int low, int high)
{
if (low > high) //查找不到时返回0
return 0;
mid = (low + high) / 2;
if (key == ST.elem[mid].key)
return mid;
else if (key < ST.elem[mid].key)
{
high = mid - 1;
Search_Bin(ST, key, low, high); //递归在前半区进行查找
}
else
{
low = mid + 1;
Search_Bin(ST, key, low, high); //递归在后半区进行查找
}
}
-
性能分析——判定树
例如有如下的有序表,其每个元素的查找次数如下,

CiC_iCi表示每个元素的查找次数。
上图中的每个结点从查找次数的角度来看,可以改写成树的结构——判定树,如下图,


圆形——内部点,代表查找成功的情况。
矩形——外结点,代表查找不成功的情况。- 查找成功:
比较次数=路径上的结点数=结点的层数
比较次数≤树的深度=⌊log2n+1⌋比较次数 \le 树的深度 = \left\lfloor {\log _2^n + 1} \right\rfloor比较次数≤树的深度=⌊log2n+1⌋ - 查找不成功:
比较次数=路径上的内部结点数
比较次数≤⌊log2n+1⌋比较次数 \le \left\lfloor {\log _2^n + 1} \right\rfloor比较次数≤⌊log2n+1⌋ - 平均查找长度ASL(成功时):
设表长n=2n−1n=2^n-1n=2n−1,则h=log2n+1h = \log _2^{n + 1}h=log2n+1(此时,判定树为深度=h的满二叉树),且表中每个记录的查找概率相等:Pi=1/nP_i=1/nPi=1/n,则ASL为,
ASL=1n∑j=1hj⋅2j−1=n+1nlog2n+1−1≈log2n+1−1(n>50)ASL = \frac{1}{n}\sum\limits_{j = 1}^h {j \cdot {2^{j - 1}}} = \frac{{n + 1}}{n}\log _2^{n + 1} - 1 \approx \log _2^{n + 1} - 1(n > 50)ASL=n1j=1∑hj⋅2j−1=nn+1log2n+1−1≈log2n+1−1(n>50)
其中j表示第j层的每个结点要比较的次数,2j−12^{j-1}2j−1表示第j层的结点数。
- 查找成功:
-
优缺点:
- 优点:效率比顺序表高,时间复杂度为O(logn)O(logn)O(logn)
- 缺点:只适用于有序表,且限于顺序存储结构(对线性链表无效)
本文深入讲解了折半查找算法的工作原理,包括非递归和递归实现方式,并分析了其性能,如判定树、平均查找长度及优缺点。适合对算法优化感兴趣的读者。
1170

被折叠的 条评论
为什么被折叠?



