zoukankan      html  css  js  c++  java
  • 二分查找和斐波那契查找

    二分查找

    说明:查找的数组或列表必须是有序的,若无序,先进行排序

    复杂度:时间复杂度 O(log2n),空间复杂度O(n)

    C++源码(递归和非递归两个版本)

    #include <iostream>
    using namespace std;
    
    int a[] = { 1, 2, 3, 4, 5, 6, 8 };
    
    int BinarySearch1(int l, int r, int value)
    {
    	int mid = (l + r) / 2;
    	if (l == r && a[l] != value)
    		return -1;
    	if (a[mid] == value)
    		return mid;
    	if (a[mid] > value)
    		return BinarySearch1(l, mid - 1, value);
    	else
    		return BinarySearch1(mid + 1, r, value);
    	
    }
    
    
    int BinarySearch2(int value){
    	int l = 0;
    	int r = sizeof(a) / sizeof(a[0]) - 1;
    	while (l <= r){
    		int mid = (l + r) / 2;
    		if (a[mid] == value)
    			return (l + r) / 2;
    		if (a[mid] > value)
    			r = mid - 1;
    		else
    			l = mid + 1;
    	}
    	return -1;
    }
    
    
    int main(void)
    {
    	
    	cout << "Binary Search (recursive) result: " << BinarySearch1(0, sizeof(a) / sizeof(a[0]) - 1, 5) << endl;;
    	cout << "Binary Search (no recursive) result: " << BinarySearch2(4) << endl;
    }
    

     

    斐波那契查找

     在介绍斐波那契查找算法之前,我们先介绍一下很它紧密相连并且大家都熟知的一个概念——黄金分割。

      黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二,较大部分与较小部分之比等于整体与较大部分之比,其比值约为1:0.618或1.618:1。

      0.618被公认为最具有审美意义的比例数字,这个数值的作用不仅仅体现在诸如绘画、雕塑、音乐、建筑等艺术领域,而且在管理、工程设计等方面也有着不可忽视的作用。因此被称为黄金分割。

      大家记不记得斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(从第三个数开始,后边每一个数都是前两个数的和)。然后我们会发现,随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618,利用这个特性,我们就可以将黄金比例运用到查找技术中。

      基本思想:也是二分查找的一种提升算法,通过运用黄金比例的概念在数列中选择查找点进行查找,提高查找效率。同样地,斐波那契查找也属于一种有序查找算法。
      相对于折半查找,一般将待比较的key值与第mid=(low+high)/2位置的元素比较,比较结果分三种情况:

      1)相等,mid位置的元素即为所求

      2)>,low=mid+1;

         3)<,high=mid-1。

      斐波那契查找与折半查找很相似,他是根据斐波那契序列的特点对有序表进行分割的。他要求开始表中记录的个数为某个斐波那契数小1,及n=F(k)-1;

     开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1),比较结果也分为三种

      1)相等,mid位置的元素即为所求

      2)>,low=mid+1,k-=2;

      说明:low=mid+1说明待查找的元素在[mid+1,high]范围内,k-=2 说明范围[mid+1,high]内的元素个数为n-(F(k-1))= Fk-1-F(k-1)=Fk-F(k-1)-1=F(k-2)-1个,所以可以递归的应用斐波那契查找。

      3)<,high=mid-1,k-=1。

      说明:low=mid+1说明待查找的元素在[low,mid-1]范围内,k-=1 说明范围[low,mid-1]内的元素个数为F(k-1)-1个,所以可以递归 的应用斐波那契查找。

      复杂度分析:最坏情况下,时间复杂度为O(log2n),且其期望复杂度也为O(log2n)。
    #include <iostream>
    #include <vector>
    using namespace std;
    const int MAX_SIZE = 20;
    
    int a[] = { 1, 5, 15, 22, 25, 31, 39, 42, 47, 49, 59, 68, 88 };
    
    void Fibonacci(int F[])
    {
    	F[0] = 0;
    	F[1] = 1;
    	for (size_t i = 2; i < MAX_SIZE; i++)
    		F[i] = F[i - 1] + F[i - 2];
    	
    }
    
    int FibonacciSearch(int value)
    {
    	int F[MAX_SIZE];
    	Fibonacci(F);
    	int n = sizeof(a) / sizeof(int);
    
    	int k = 0;
    	while (n > F[k] - 1)
    		k++;
    	vector<int> temp;
    	temp.assign(a, a + n);
    	for (size_t i = n; i < F[k] - 1; i++)
    		temp.push_back(a[n - 1]);
    
    	int l = 0, r = n - 1;
    	while (l <= r)
    	{
    		int mid = l + F[k - 1] - 1;
    		if (temp[mid] < value){
    			l = mid + 1;
    			k = k - 2;
    		}
    		else if (temp[mid] > value){
    			r = mid - 1;
    			k = k - 1;
    		}
    		else{
    			if (mid < n)
    				return mid;
    			else
    				return n - 1;
    		}
    	}
    	return -1;
    }
    
    int main()
    {
    
    	int index = FibonacciSearch(88);
    	cout << index << endl;
    
    }
    
  • 相关阅读:
    基于MINA实现server端心跳检测(KeepAliveFilter)
    TCP的TIME_WAIT快速回收与重用
    HDU4183 起点到终点再到起点 除起点每点仅经过一次 网络流
    oracle union 注入工具
    sqlmap注入技巧收集
    sqlmap的一些小技巧
    FCKeditor漏洞利用
    WAF绕过的技巧
    杨辉三角
    Oracle 常用入侵命令
  • 原文地址:https://www.cnblogs.com/willwu/p/6001980.html
Copyright © 2011-2022 走看看