【原创】启发式查询

##启发式查询**|Cacl_Search
此算法为bzy原创,转载务必获得允许(QQ:1143710044)

从一个单调队列中查询一个数字的位置一直是一个困扰人们的问题。
这个问题一直有一个十分简易的方法叫做
搜索**
实现如下:

int normal_Search(int *line,int value,int ub){
	for(int i = 0;i <= ub ;i ++){
		if(line[i] == value)return i; 
	}
	return 0;
}
O(n)的算法很显然有些慢,在运算100'000数据量1000'000次直接bz(1000s),显然不能满足~~人们日益增长的追求美好生活的追求~~,于是聪明的先祖想出了**二分查找** ###二分查找**|**Bianry_Search 学过OI/ACM肯定学过这个算法,它在计算机领域广泛运用,所以关于它的描述就从略。 二分查找是一种将单调队列从中间分快的方法,是已知运用最广泛的算法之一,代码如下: ``` int Binary_search(int *line,int value,int ub){ int down = 0,up = ub; while(1){ int mid = (up + down)>>1; if (line[mid] == value)return mid; if (line[mid] > value){ up = mid - 1; }else { down = mid + 1; } } return 0; } ``` 看完代码,其精髓思想便一目了然,$O(log_2 n)$的时间复杂度和极地的常数使得它速度极快,同普通搜索一样的数据量它用时仅为1.6 - 2.0秒. 但是本着精益求精的思想,bzy想出了一个算法可以在常数上胜过二分查找,这就是**启发式查询**。 !!!重头戏登场

###启发式查询**|**Cacl_Search

已知单调队列 { L i n e i Line_i Linei},其长度为ubount其对首记做Line[ 1 ],其尾记做Line[ ub ],所搜索的值记做Value,由此,我们可以近似估计Line 是一个等差数列,即可估计Value的位置大概在:
estimate = 1+(ub-1) *(value-line[1]) / (line[ub]-line[1]);
当然这个式子估计的位置只是估计值,不一定正确,当我,们可以确定范围,用Line[ estimate ]与value比较,如果大则范围在1 - estimate之间,否则在estimate-ub之间,直到有一个正确的estimate出现则返回即可,
代码如下:

inline const int Cacl_Search(int *line,const int value,const int ub){
	int down = 0;register int up=ub;
	while(1){
		register int estimate = down + 
		(long long)(up - down) *
		(long long)(value -line[down]) / 
		(line[up] - line[down]);
		if(estimate == down) ++ estimate ;
        if(estimate == up  ) -- estimate ;
		if(line[estimate] == value)return estimate;
		(line[estimate] < value?down:up) = estimate;
	}
	return 0;
}
在常数优化下运行同样数据只需1.1 - 1.2s,显然比二分查找快了很多. 这个算法时间复杂度不好估计,但效率较高,在卡常数时有一定作用. ###后记**|**RP_search 最后送给大家一个测试人品的算法: ``` int down = 0,up = ub; srand(233);'种子随意,看人品 while(1){ if(up == down)return down;
	register int estimate = down + 
	(long long)(up - down) *
	(long long)(value -line[down]) / 
	(line[up] - line[down]);
	if(line[estimate] == value)return estimate;
	int mid = down + rand()*rand()%(up - down);
	if (line[mid] == value)return mid;
	if(line[mid]>value){
		up = mid - 1;
	}else {
		down = mid + 1;
	}
}
return 0;
<font size = 1>此算法为bzy原创,转载务必获得允许(QQ:1143710044)</font>
<font size = 4>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值