四种基础查找板子

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         if(a[i]==value)
            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 InsertionSearch(value,mid+1,high);
        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 //用这两个头文件好,因为用#include "stdafx.h"会报错 
using namespace std;
const int max_size=20;//斐波那契数组的长度
 
/*构造一个斐波那契数组*/ 
/*void Fibonacci(int *F)//指针指数组 
{
    F[0]=0;
    F[1]=1;
    for(int i=2;i         F[i]=F[i-1]+F[i-2];//斐波那契数列规律 
}
/*定义斐波那契查找法*/  
/*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     temp[i]=a[n-1];
  
    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            return mid; //若相等则说明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<     return 0;
}
 

你可能感兴趣的:(数据结构,算法,二分查找)