1.二分查找
2. 顺序查找
3. 插值查找
4. 斐波那契查找
1.二分查找(期望时间复杂度为O(log2n))
假设在[begin,end)范围内搜索某个元素 v,mid == (begin + end)/ 2
①如果v < m,去[begin , mid)范围内二分搜索
②如果v > m,去[mid + 1, end)范围内二分搜索
③如果v == m ,直接返回 mid
end指的是数组的长度。
//例题:假设我们要从一个排好序的数组里 {1, 3, 4, 6, 7, 8, 10, 13, 14} 查看一下数字 7 是否在里面,如果在,返回它的下标,否则返回 -1。
#include
int a[5],n;
int find(int x) //二分查找
{
int l=1,r=n;
while (l
int mid=l+(r-l)/2;
if (a[mid]>=x) r=mid;
else l=mid+1;
}
if (a[l]==x) return l; //找到了就输出他的位置
else return -1; // 没找到输出-1
}
int main()
{ a[0]=2;
a[1]=3;
a[2]=4;
a[3]=7;
a[4]=5;
printf("%d",find(6));
return 0;
}
2.顺序查找(时间复杂度为O(n))
基本思想:顺序查找也称为线形查找,属于无序查找算法。
从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;
若扫描结束仍没有找到关键字等于k的结点,表示查找失败。
//顺序查找
#include
int a[5],n;
int SequenceSearch(int value, int n)
{
int i;
for(i=0; i
return i;
return -1;
}
int main()
{ a[0]=1;
a[1]=2;
a[2]=4;
a[3]=6;
a[4]=7;
printf("%d",SequenceSearch(4,5));
return 0;
}
3.插值查找(查找成功或者失败的时间复杂度均为O(log2(log2n)))(非常好的算法!!!!!)
在介绍插值查找之前,首先考虑一个新问题,为什么上述算法一定要是折半,而不是折四分之一或者折更多呢?
打个比方,在英文字典里面查“apple”,你下意识翻开字典是翻前面的书页还是后面的书页呢?如果再让你查“zoo”,你又怎么查?
很显然,这里你绝对不会是从中间开始查起,而是有一定目的的往前或往后翻。
同样的,比如要在取值范围1 ~ 10000 之间 100 个元素从小到大均匀分布的数组中查找5, 我们自然会考虑从数组下标较小的开始查找。
经过以上分析,折半查找这种查找方式,不是自适应的(也就是说是傻瓜式的)。二分查找中查找点计算如下:
mid=(low+high)/2, 即mid=low+1/2*(high-low);
通过类比,我们可以将查找的点改进为如下:
mid=low+(key-a[low])/(a[high]-a[low])*(high-low)
所以插值查找相当于改良版的二分查找!!!!
基本思想:基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率
。
#include
int a[5];
int InsertionSearch(int value,int low,int high)
{ int mid = low+(value-a[low])/(a[high]-a[low])*(high-low);
if(a[mid]==value)
return mid;
if(a[mid]>value)
return InsertionSearch(value,low,mid-1);
if(a[mid]
return -1;
}
int main()
{ a[0]=1;
a[1]=2;
a[2]=4;
a[3]=6;
a[4]=7;
printf("%d",InsertionSearch(6,0,4));
}
4.斐波那契查找(最坏情况下,时间复杂度为O(log2n),且其期望复杂度也为O(log2n))
大家记不记得斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89……
(从第三个数开始,后边每一个数都是前两个数的和)。
然后我们会发现,随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618。
利用这个特性,我们就可以将黄金比例运用到查找技术中。
#include
#include
using namespace std;
const int max_size=20;//斐波那契数组的长度
/*构造一个斐波那契数组*/
/*void Fibonacci(int *F)//指针指数组
{
F[0]=0;
F[1]=1;
for(int i=2;i
}
/*定义斐波那契查找法*/
/*int Fibonacci_Search(int *a, int n, int key) //a为要查找的数组,n为要查找的数组长度,key为要查找的关键字
{
int low=0;
int high=n-1;
int F[max_size];
Fibonacci(F);//构造一个斐波那契数组F
int k=0;
while(n>F[k]-1)//计算n位于斐波那契数列的位置
++k;
int * temp;//将数组a扩展到F[k]-1的长度,开始申请动态数组
temp=new int [F[k]-1];//new int和memcpy,delete构成完整操作:动态申请内存空间
memcpy(temp,a,n*sizeof(int));
for(int i=n;i
while(low<=high)
{
int mid=low+F[k-1]-1;
if(key
high=mid-1;
k-=1;
}
else if(key>temp[mid])
{
low=mid+1;
k-=2;
}
else
{
if(mid
else
return n-1; //若mid>=n则说明是扩展的数值,返回n-1
}
}
delete [] temp;
return -1;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[] = {0,16,24,35,47,59,62,73,88,99};
int key=100;
int index=Fibonacci_Search(a,sizeof(a)/sizeof(int),key);
cout<
}