任务描述
本关任务:采用二分查找算法实现查找有序数组里大于等于 K 的第一个数字。
相关知识
查找的概念
对于计算机信息而言,所谓查找是在一个含义众多数据元素(记录)的查找表中找出某个特定的数据元素(记录)。其中,涉及的基本概念有: (1)查找表:是由同一类型的数据元素(或记录)构成的集合。 (2)静态查找表:仅能对查找表进行查找操作,不能进行改动的表。 (3)动态查找表:对查找表除进行查找操作外,还能进行插入、删除和修改操作的表。 (4)关键字:某个特定的词称为关键字,数据元素(或记录)中某个项或组合项的值,用它可以标识一个数据元素(或记录)。如果此关键字可以唯一地标识一条记录,则称该关键字为主关键字。 (5)查找:根据给定的某个值,在表中确定一个其关键字等于给定值的记录或数据元素。若表中存在这样一个记录,则称查找是成功的,此时查找的结果为给出整个记录的信息,或指示该记录在查找表中的位置;若表中不存在其关键字等于给定值的记录,则称查找不成功,此时查找的结果应给出一个“空”记录或“空指针”。
查找表的存储结构: 线性结构:顺序表,链表 树形结构:二叉排序树,B-树 散列结构:哈希表(散列表)
查找性能的评价指标: 平均查找长度ASL: 在查找过程中,给定值K与关键字比较次数的期望值
n ——查找表中记录个数 Ci——查找到第i条记录时,K与关键字的比较次数 Pi——查找第i条记录的概率
静态查找表采用顺序存储结构,顺序表是一种典型的顺序存储结构,本关静态查找表采用顺序表组织方式。
二分查找又称折半查找,折半查找要求顺序表中元素是有序的,即表中元素按关键字有序,假设有序顺序表是递增有序的。
二分查找算法思想
设R[low..high]
是当前的查找区间,首先确定该区间的中点位置mid=(low+high)/2
;然后将待查的k
值与R[mid].key
比较:
- 若
R[mid].key=k
,则查找成功并返回该元素的逻辑序号; - 若
R[mid].key>k
,则由表的有序性可知R[mid..n-1].key
均大于k
,因此若表中存在关键字等于k
的元素,则该元素必定在位置mid
左子表R[0..mid-1
]中,故新的查找区间是左子表R[0..mid-1]
; - 若
R[mid].key<k
,则要查找的k
必在位置mid
的右子表R[mid+1..n-1]
中,即新的查找区间是右子表R[mid+1..n-1]
。
二分查找算法分析
折半查找过程构成一个判定树,把当前查找区间的中间位置上的记录作为根,左子表和右子表中的记录分别作为根的左子树和右子树。 例如:n=10即R[0..9]
的全部查找情况如图所示:
当折半查找表中元素个数n
较大时,可以将整个判定树近似看成是一棵满二叉树,所有的叶子结点集中在同一层。不考虑外部结点,树的高度h=log2(n+1)
。 所以有:
查找成功: ASL=(1×1 + 2×2 + 3×4 + 4×3)/10 = 29/10
查找失败: ASL=(5×3 + 6×4)/11 = 39/11
编程要求
请在右侧编辑器的命名空间内填写相关代码,实现采用二分查找算法实现查找有序数组里大于等于K的第一个数字。
本关静态查找表采用顺序表组织方式,并假设顺序表中数据元素类型的定义如下:
typedef int KeyType; //根据需要设定数据类型
typedef struct
{
KeyType key; //关键字字段
}ElemType;
typedef struct
{
ElemType r[MAXSIZE];
int length; // 表的长度
} SSTable;
测试说明
平台会对你编写的代码进行测试:
测试输入: 第一行 1 个整数 n 表示有序数组的大小 第二行 n 个整数表示数组里的元素 第三行 1 个整数 K
实际输出: 你返回的值
#include <stdio.h>
#define MAXSIZE 100
typedef int KeyType; //根据需要设定数据类型
typedef struct
{
KeyType key; //关键字字段
}ElemType;
typedef struct
{
ElemType r[MAXSIZE];
int length; // 表的长度
} SSTable;
int BinSearch(SSTable t,int n,int k) //拆半查找算法
{
/********** Begin **********/
int low = 0,high = n - 1;
int mid = 0;
while (low <= high){
mid = (low + high) / 2;
if (k < t.r[mid].key){
high = mid - 1;
}
else if (k > t.r[mid].key){
low = mid + 1;
}
else
return mid;
}
if (low > high)
if (k > t.r[mid].key)
return mid + 1;
else return mid;
/********** End **********/
}
int main()
{
int i,j;
int n,k;
SSTable t;
scanf("%d",&n);
for (i=0;i<n;i++)
scanf("%d",&t.r[i].key);
scanf("%d",&k);
j=BinSearch(t,n,k);
if (j>=0 && j<n)
printf("%d\n",t.r[j].key);
else
printf("-1\n");
}