精华内容
下载资源
问答
  • 对于有序列表使用的查找算法
    千次阅读
    2021-07-10 10:48:35

    1.     顺序查找,时间复杂度为O(n)

    2.     二分查找,时间复杂度为O(log2n)

    3.     插值查找,关键字分布又比较均匀, 时间复杂度为O(log2(log2n))

    4.     斐波那契查找,时间复杂度为O(log2n)

    5.     树表查找

    a)     二叉树查找算法,插入和查找的时间复杂度均为O(logn)

    b)     红黑树,logn

    c)     B树和B+树,O(log n)

    6.     分块查找,关键字构成一个索引表

    7.      哈希查找,以空间换时间的算法

    折半查找,每次都是1/2,设寻找t次,等式为2t =n,n为数据的总数

    更多相关内容
  • 三种有序表的查找算法

    千次阅读 2019-08-26 11:52:06
    三种有序表查找及其心得体会有序查找算法简介排序算法种类二分查找算法时间复杂度插值查找算法时间复杂度斐波那契查找算法时间复杂度总结参考文献 有序查找算法简介 查找的是一个有序线性表,并进行查找操作的...

    有序表查找算法简介

    查找的是一个有序线性表,并进行查找操作的查找表

    排序算法种类

    按照算法复杂程度分类
    这里主要以二分查找,插值查找,斐波那契查找为例子

    二分查找

    折半查找(Binary Search)技术,又称为二分查找。它的前提是线性表中的记录必须是关键码有序(通常从小到大有序),线性表必须采用顺序存储。折半查找的基本思想是:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区继续查找。

    • 中心思想:有序取中,比较左右,折半查找。

    在这里插入图片描述

    算法

    1  int Binary_Search(int *a,int n,int key)
    2  {
    3      int low,high,mid;
    4      int low=1;
    5      int high=n;
    6      while(low<=high)
    7     {
    8          mid=(low+high)/2; 
    9          if(key<a[mid])
    10            high=mid-1; 
    11         else if (key>a[mid])
    12            1ow=mid+1; 
    13         else 
    14            return mid;
    15    }
    16 }
    

    时间复杂度

    具有n个结点的完全二又树的深度为 ⌊ log ⁡ 2 n ⌋ + 1 \lfloor \log _2n \rfloor +1 log2n+1。在这里尽管折半查找判定二叉树并不是完全二叉树,但同样相同的推导可以得出,最坏情况是查找到关键字或查找失败的次数为 ⌊ log ⁡ 2 n ⌋ + 1 \lfloor \log _2n \rfloor +1 log2n+1

    插值查找

    插值查找(Interpolation Search)是根据要查找的关键字key与查找表中最大最小记录的关键字比较后的查找方法,其核心就在于插值的计算公式 k e y − a [ l o w ] a [ h i g h ] − a [ l o w ] \frac{key-a\left[ low \right]}{a\left[ high \right] -a\left[ low \right]} a[high]a[low]keya[low]

    • 中心思想:插值公式

    在这里插入图片描述
    在这里插入图片描述

    算法

    1  int Interpolation_Search(int *a,int n,int key)
    2  {
    3      int low,high,mid;
    4      int low=1;
    5      int high=n;
    6      while(low<=high)
    7     {
    8          mid=low+(high-1ow)*(key-a[low])/(a[highl-a[low]);/*插值改动处*/
    9          if(key<a[mid])
    10            high=mid-1; 
    11         else if (key>a[mid])
    12            1ow=mid+1; 
    13         else 
    14            return mid;
    15    }
    16 }
    

    时间复杂度

    时间复杂度:O(logn)

    斐波那契查找

    斐波那契查找(Fibonaci Search),它是利用了黄金分割原理来实现的。

    • 中心思想:将线性表都成斐波那契数列,然后后黄金分割取上下限

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    算法

    1  int Fibonacci_Search(int *a,int n,int key)
    2  {
    3       int low,high,mid,i,k;
    4   	low=1;
    5	    high=n;
    6   	k=0;
    7   	while(n>F[k]-1)
    8   	   k++;
    9   	for(i=n;i<=f[k]-1;i++)
    10   	   a[i]=a[n];
    11   	while(low<=high)
    12   	{
    13   		mid=low+f[k-1]-1;
    14   		if(key<a[mid])
    15   		{
    16   			high=mid-1;
    17   			k=k-1;
    18   		}
    19   		else if(key>a[mid])
    20   		{
    21   			low=mid+1;
    22   			k=k-2;
    23   		}
    24   		else
    25   		{
    26   			if(mid<=n)
    27   			   return mid;
    28   			else 
    29  			   return n;
    30   		}
    31   	}
    32   	return 0;
    33   } 
    

    时间复杂度

    尽管斐波那契查找的时间复杂也O(logn),但就平均性能来说,斐波那契查找要优于折半查找。可惜如果是最坏情况,比如这里key=1,那么始终都处于左侧长半区在查找,则查找效率要低于折半查找。

    总结

    1. 应该说,三种有序表的查找本质上是分隔点的选择不同,各有优劣,实际开发时可根据数据的特点综合考虑再做出选择。
    2. 未知的数据首先考虑二分查找
    3. 均匀的数据适合插值查找
    4. 如果要查找的记录在右侧,则左侧的数据都不用再判断了,不断反复进行下去,对处于当中的大部分数据,斐波那契查找工作效率要高一些。

    参考文献

    [[1]] 程杰. 大话数据结构[M]. 清华大学出版社, 2011.
    [[2]] 啊哈磊. 啊哈! 算法[M]. 人民邮电出版社, 2014.

    展开全文
  • 主要介绍了Python查找两个有序列表中位数的方法,结合实例形式分析了Python基于归并算法遍历、计算有序列表相关操作技巧,需要的朋友可以参考下
  • 这篇文章主要介绍了python有序查找算法 二分法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 二分法是一种快速查找的方法,时间复杂度低,逻辑简单...
  • 主要介绍了PHP有序表查找之插值查找算法,简单分析了插值查找算法的概念、原理并结合实例形式分析了php实现针对有序表插值查找的相关操作技巧,需要的朋友可以参考下
  • 本文实例讲述了PHP有序查找之二分查找(折半查找算法。分享给大家供大家参考,具体如下: 简介: 二分查找技术,又称为折半查找。它的前提是线性表中的记录必须是关键码有序(通常从小到达有序),线性表必须...
  • 本文实例讲述了Python有序查找算法之二分法。分享给大家供大家参考,具体如下: 二分法是一种快速查找的方法,时间复杂度低,逻辑简单易懂,总的来说就是不断的除以2除以2… 例如需要查找有序数组arr里面的某个...
  • 本文实例讲述了JavaScript使用二分查找算法在数组中查找数据的方法。分享给大家供大家参考。具体分析如下: 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入...
  • 因此,折半查找方法适用于不经常变动而查找频繁的有序列表。 【算法思想】首先,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置...
  • JS二分查找算法详解

    2020-11-28 15:50:47
    二分法查找,也称折半查找,是一种在有序数组中查找特定元素的搜索算法查找过程可以分为以下步骤: (1)首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,...
  • c# 二分查找算法

    2020-09-04 22:56:26
    折半搜索,也称二分查找算法、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法
  • 有序顺序表的二分查找的递归算法.pdf
  • 有序查找算法总结

    千次阅读 2018-01-17 20:22:31
    有序表:按一定顺序排列的表。  1、折半查找:又称二分查找,直接上代码、 public int BinarySerch(int[] a,key){ int low=1,high=a.length,mid; while( low ){ mid = low + (high - low) / 2; if( key [mid]){...

     有序表:按一定顺序排列的表。

    有序表结构

          1、折半查找:又称二分查找,直接上代码、

    public int BinarySerch(int[] a,key){
          int low=1,high=a.length,mid;
          while( low <= high ){
    	mid = low + (high - low) / 2;
    	if( key < a[mid]){
    	     high = mid - 1;
    	 }else if( key > a[mid] ){
    	     low = mid + 1;
    	 }else{
    	     return mid
    	 }
          }
    
          return 0;
    }

    分割点 使用 (m + n) /2,因为当遇到m、n的数值过大时,可能会出现bug(溢出),所以使用
     n + (m - n)/2;

    2、 继续上面的想法,我们可以通过规律公式来确定key的大概范围,来减少查找次数。

    插值查找  ,(key - a[low]) / (a[high] - a[low]).

    见上述代码。将 mid 改成

    mid = low + (high - low) * ( key - a[low]) /(a[high] - a[low])

    3、斐波那契查找:

    学编程的就没有入不知道斐波那契,特别是它的循环自己调用自己,对是递归。

    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个,所以可以递归 的应用斐波那契查找。以下代码是C写的,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    #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;
     
    }
    总结: 三种查找法,本质上是分割点的不同。它们的查找时间复杂度都是O(log2 n);
    二分查找 适用 表中数据不再变化,且有序。若是频繁想表中插入修改数据,不适用。
    插值查找 总体笔二分查找要快一些,但是当表中数据相差非常不均与的情况下,没有二分快;
    斐波那契 总体比二分好一些。
    计算规则方面: 斐波那契只涉及简单加减效率 F(k)-1 > 折半效率(high - low)/2 >
    插值查找效率 (key - a[low]) / (a[high] - a[low])

     

    展开全文
  • 查找算法之二分查找算法

    千次阅读 2022-05-18 16:02:02
    图文并茂带你入门二分查找算法 原理 二分查找(Binary Search)算法,也叫折半查找算法。二分查找的思想非常简单,有点类似分治的思想。二分查找针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比,将待...

    图文并茂带你入门二分查找算法

    原理

    二分查找(Binary Search)算法,也叫折半查找算法。二分查找的思想非常简单,有点类似分治的思想。二分查找针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。

    为了方便理解,我们以数组1, 2, 4, 5, 6, 7, 9, 12, 15, 19, 23, 26, 29, 34, 39,在数组中查找26为例,制作了一张查找过程图,其中low标示左下标,high标示右下标,mid标示中间值下标

    img

    二分查找的过程就像上图一样,如果中间值大于查找值,则往数组的左边继续查找,如果小于查找值这往右边继续查找。二分查找的思想虽然非常简单,但是查找速度非常长,二分查找的时间复杂度为O(logn)。虽然二分查找的时间复杂度为O(logn)但是比很多O(1)的速度都要快,因为O(1)可能标示一个非常大的数值,比例O(1000)。我们来看一张二分查找与遍历查找的效率对比图。

    img

    ❝ 图片来源网络

    从图中可以看出二分查找用了三步就找到了查找值,而遍历则用了11步才找到查找值,二分查找的效率非常高。但是二分查找的局限性非常大。那二分查找有哪些局限性呢?

    局限性

    二分查找依赖数组结构

    二分查找需要利用下标随机访问元素,如果我们想使用链表等其他数据结构则无法实现二分查找。

    二分查找针对的是有序数据

    二分查找需要的数据必须是有序的。如果数据没有序,我们需要先排序,排序的时间复杂度最低是 O(nlogn)。所以,如果我们针对的是一组静态的数据,没有频繁地插入、删除,我们可以进行一次排序,多次二分查找。这样排序的成本可被均摊,二分查找的边际成本就会比较低。

    但是,如果我们的数据集合有频繁的插入和删除操作,要想用二分查找,要么每次插入、删除操作之后保证数据仍然有序,要么在每次二分查找之前都先进行排序。针对这种动态数据集合,无论哪种方法,维护有序的成本都是很高的。

    所以,二分查找只能用在插入、删除操作不频繁,一次排序多次查找的场景中。针对动态变化的数据集合,二分查找将不再适用

    数据量太小不适合二分查找

    如果要处理的数据量很小,完全没有必要用二分查找,顺序遍历就足够了。比如我们在一个大小为 10 的数组中查找一个元素,不管用二分查找还是顺序遍历,查找速度都差不多,只有数据量比较大的时候,二分查找的优势才会比较明显。

    数据量太大不适合二分查找

    二分查找底层依赖的是数组,数组需要的是一段连续的存储空间,所以我们的数据比较大时,比如1GB,这时候可能不太适合使用二分查找,因为我们的内存都是离散的,可能电脑没有这么多的内存。

    代码实现

    二分查找可以使用循环或者递归来实现,我们来看看两种实现方式的代码。

    循环

    /**
         * 循环版二分查找
         *
         * @param nums  数组
         * @param n     数组长度
         * @param value 要查找的值
         * @return
         */
        private static int bserach(int[] nums, int n, int value) {
            int low = 0;
            int high = n - 1;
            while (low <= high) {
                // 找出中间下标 
                int mid = low + ((high - low) >> 1);
                if (nums[mid] > value) {
                    high = mid - 1;
                } else if (nums[mid] < value) {
                    low = mid + 1;
                } else {
                    return mid;
                }
            }
    
            return -1;
        }
    

    递归

    /**
         * 递归算法实现二分查找
         *
         * @param nums  数组
         * @param low   左下标
         * @param high  右下标
         * @param value 要查找的值
         * @return
         */
        private static int recursiveBserach(int[] nums, int low, int high, int value) {
    
            if (low > high) return -1;
    
            // 找出中间下标
            int mid = low + ((high - low) >> 1);
    
            if (nums[mid] == value) {
                return mid;
    
            } else if (nums[mid] > value) {
                return recursiveBserach(nums, low, mid - 1, value);
            } else {
                return recursiveBserach(nums, mid + 1, high, value);
            }
        }
    

    二分查找的代码实现起来比较简单,需要说明的地方是中间值的计算,中间值得计算有两种方式,方式一:int mid = (low +high)>>1,方式二:int mid = low + ((high - low) >> 1)。方式一存在溢出的风险,当lowhigh比较大时,有可能会导致mid的值错误,从而使程序出错。方式二则可以保证生成的mid一定大于low,小于high

    上面的二分查找比较简单,我们来看看变形的二分查找。

    查找第一个等于给定值的元素

    比如我们给定数组1,2,3,4,4,4,5,6,7,7,8,9,我们需要查找第一个等于4的元素。

        /**
         * 查找第一个等于给定值的元素
         *
         * @param nums
         * @param length
         * @param value
         * @return
         */
        private static int bsearchFirstValue(int[] nums, int length, int value) {
            int low = 0;
            int high = length - 1;
            while (low <= high) {
                int mid = low + ((high - low) >> 1);
                if (nums[mid] > value) {
                    high = mid - 1;
                } else if (nums[mid] < value) {
                    low = mid + 1;
                } else {
                    // 判断当前是第一个元素或者前一个元素不等于要查找的值,则返回下标,如果前一个元素也等于要查找的值,则继续往前查找。
                    if ((mid == 0) || (nums[mid - 1] != value)) return mid;
                    else high = mid - 1;
                }
            }
            return -1;
        }
    

    其他的都差不多,主要的区别是在nums[mid]==value时候,因为我们要查找的是第一个等于给定值的元素,所以我们需要判断mid的前一个元素等不等于给定值,如果前一个元素也等于给定值,则需要继续往左边查找。

    查找第一个大于给定值的元素

    比如我们给定数组1,2,3,4,4,4,5,6,7,7,8,9,15,26,34,45,我们随便输入一个值,这个值可以是数组里面的值,也不可不在数组里面,查找出第一个比给定值大的元素。

    /**
         * 查找第一个大于给定值的元素
         *
         * @param nums   数组
         * @param length 数组的长度
         * @param value  给定的值
         * @return
         */
        private static int bserachFirstOverVlaue(int[] nums, int length, int value) {
            int low = 0;
            int high = length - 1;
            while (low <= high) {
                int mid = low + ((high - low) >> 1);
                if (nums[mid] > value) {
                    // 判断当前是第一个元素或者前一个元素小于等于给定值,则返回下标,如果前一个元素大于给定的值,则继续往前查找。
                    if ((mid == 0) || nums[mid - 1] <= value) return mid;
                    else high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return -1;
        }
    

    我们需要判断当nums[mid] > value时,nums[mid-1]是否小于或者等于给定值,如果是则mid就是第一个大于给定值的元素,如果不是这继续往左边查找。

         low = mid + 1;
            }
        }
        return -1;
    }
    
    
    我们需要判断当`nums[mid] > value`时,`nums[mid-1]`是否小于或者等于给定值,如果是则`mid`就是第一个大于给定值的元素,如果不是这继续往左边查找。
    
    以上就是关于二分查找的相关知识,二分查找虽然性能比较优秀,但应用场景也比较有限,底层必须依赖数组,并且还要求数据是有序的。所以我们在选用算法时需要从多方面考虑。
    
    展开全文
  • 有序表查找---折半查找算法

    万次阅读 2019-03-10 20:00:31
    折半查找的基本思想是:在有序表中,取中间值为比较对象,如果给定的值和中间值的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定的值大于中间值的关键字,则在中间...
  • 二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。 前提:线性表中的记录...
  • 查找算法 1顺序查找 顺序查找的基本思想是从第一个数据开始按顺序逐个将数据与给定的数据(查找键)进行比较若某个数据和查找键相等则查找成功输出所查找数据的位置反之输出未找到 2对分查找 对分查找又称二分查找是一...
  • 有序数组的最快的查找算法

    千次阅读 2020-03-20 11:15:17
    有一个有序的数组,有没有最快的方法查找到里面的一个元素是否存在?存在返回下标,不存在返回-1。 部分人回答用循环,多数人想到用数组的findIndex方法。 很少的人知道这个题是要用二分查找的。 这个题主要是想看...
  • 在这里总结一下几个基于有序查找算法,理解也不是很透彻,自己感受一下! 1.折半查找:又称二分查找,前提是数据有序,通常是从下到大有序,且必须采用顺序存储。 思想:在有序表中,取中间值进行第一次比较,...
  • C语言分块查找算法索引顺序查找算法 例如采用分块查找法在有序表 111218283956698996122135146156256298 中查找关键字为 96 的元素 査找特定关键字元素个数为 15要求用户输入有序表各元素程序输出査找成功与否若成功...
  • 因此,折半查找方法适用于不经常变动而查找频繁的有序列表。 二分查找思想 首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功; 否则利用中间位置记录将表分成...
  • 查找有序数组指定元素,返回目标元素下标,如果不存在,则插入适当位置使数组仍然保持有序,时间复杂度为O(log(n)),该算法是基本查找算法,可以用二分法。下面是代码实现。 class Solution { public: int search...
  • 本文实例讲述了PHP实现的折半查找算法。分享给大家供大家参考,具体如下: 定义:折半查找技术,也就是二分查找。它的前提是线性表中的记录必须是关键码有序(通常从大到小有序),线性表必须采用顺序存储。 折半...
  • 请写出对有序表进行折半查找的非递归算法.doc
  • 哈希查找算法

    千次阅读 2022-01-21 14:41:42
    哈希查找算法适用于大多数场景,既支持在有序序列中查找目标元素,也支持在无序序列中查找目标元素。讲解哈希查找算法之前,我们首先要搞清楚什么是哈希表。 哈希表是什么 哈希表(Hash table)又称散列表,是一种...
  • 顺序查找算法

    千次阅读 2022-01-21 14:14:31
    顺序查找算法适用于绝大多数场景,既可以在有序序列中查找目标元素,也可以在无序序列中查找目标元素。 顺序查找算法的实现思路 所谓顺序查找,指的是从待查找序列中的第一个元素开始,查看各个元素是否为要找的目标...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 165,902
精华内容 66,360
热门标签
关键字:

对于有序列表使用的查找算法