第1关:二分查找法


任务描述

本关任务:采用二分查找算法实现查找有序数组里大于等于 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的第一个数字。

本关静态查找表采用顺序表组织方式,并假设顺序表中数据元素类型的定义如下:

 
  1. typedef int KeyType; //根据需要设定数据类型
  2. typedef struct
  3. {
  4. KeyType key; //关键字字段
  5. }ElemType;
  6. typedef struct
  7. {
  8. ElemType r[MAXSIZE];
  9. int length; // 表的长度
  10. } 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");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值