查找——数据的查找(一)

定义

平常我们认为的查找,在计算机算法中,稍稍有一些不同

在计算机科学中定义为:在一些(有序的/无序的)数据元素中,通过一定的方法找出与给定关键字相同的数据元素的过程叫做查找。也就是根据给定的某个值,在查找表中确定一个关键字等于给定值的记录或数据元素。——百科

  1. 查找解决的问题的输入是:
    • 输入1:一堆有序或无序的数据元素。也就是查找的逻辑结构是基于集合的
      但是因为集合中元素和元素之间本质上没有关系,所以需要实现查找,就要把这种逻辑结构向我们平常处理的线性表、树等逻辑结构进行转换。
      值得注意的是,查找的数据元素虽然说是基于集合的,但是可以是相同的,但是如果当数据元素是主关键字的时候,是有互异性的。
    • 输入2:关键字。搜索过程中我们要输入的是key,而不是其它。key有主关键字和次关键字两种,主关键字是唯一标识数据记录的,而次关键字不是唯一的。

关键字、数据记录、数据项
如何区分这三个的关系呢,一个关键字就是一个数据项。当一个关键字(一个数据项)有互异性的时候它就可以代表一整条数据记录(数据记录是多个数据项的组合)。

  1. 查找解决的问题的输出是:

    • 一整条数据记录
  2. 查找的两种分类

    • 静态查找:就是单纯的查找,不改变数据
    • 动态查找:不仅仅是查找,查找到了还要对数据进行操作(增删)

顺序表查找

接下来我们就通过把查找的集合型逻辑结构转换为线性表的结构,再对线性表进行查找,一般利用线性表结构通常是静态查找

顺序查找

如果线性表没有顺序——

public static int sequenceSearch(int[] list, int key) {
        for (int i = 0; i < list.length; i++) {
            // 找到该元素,返回位置序号
            if (list[i] == key) {
                return i;
            }
        }
        // 没有找到
        return -1;
}

可以对顺序查找进行优化,不需要每次都判断i是否越界:设置哨兵,遇到哨兵则证明查找结束跳出循环,具体代码此处略

有序查找(有序表查找)

不同于顺序表查找,在这里我们把元素们按某种顺序进行排列好,可以进行折半查找,更快。

二分查找

对于算法,我一般都是把步骤和具体代码实现进行对应,再去分析每一步实现的代码有什么特点
算法步骤

  1. 找到中间元素,比较异同
  2. 若不同,选择其中一个半数组当成一个新数组
  3. 若相同,返回中间元素,跳出循环
  4. 重复第1、2、3步,直到数组只剩一个元素
图1

要点
1 对于算法步骤3,重复哪几步就在哪几步前面加循环,如果重复第一步,就意味着循环从第一步前就开始
2 一个数组的变化只要用“指针”标明数组的实际物理位置下标从哪里开始到哪里结束
3 找中间元素就是把头尾相加的一半((low+high)/2)
4 如何判断数组只有一个元素了——low==high

插值查找

和二分查找差别就在于,每次都会筛选按照百分比去选择数组的分割点。

二分查找是不会错过关键字的算法,但是对于分布均匀的数组,效率相较低;插值查找对于分布均匀的数组,查找效率相对较高,但是对于极端的分布的数组是效率很低的

它们的时间复杂度都是O(logn)

斐波那契查找算法

它的筛选方法也是通过分割,但是是按照黄金分割去选择分割点,除此之外思路上并没有与前面两者很大区别,算法复杂度依然是O(logn),但其优点是:整个算法只需要进行加减运算

在算法步骤上&代码上的区别:

  1. 需要增加斐波那契数列数组
  2. 对原数组需要进行补充至符合斐波那契数列的长度
  3. 分割点不同意味着mid的计算公式需要变化
  4. 分割数组的时候需要根据左右来更新下一个分割点的位置在哪(k-1或者是k-2)

线性索引查找

何为索引查找呢,就是之前我们查找都是把整个数据记录当作数组的一项,但是现在我们为了方便维护,我们就单独取相应的关键字作为索引,每次查找先查找这一个关键字,找到了之后根据关键字所带的指针找到相应的数据记录
图2

如图2,关键码里面的关键字都是一样的,只是我把关键码单独一项拿出来单独成表,便于维护。

稠密索引

如图2,把所有的数据记录的关键字都拿出来建成索引表

分块索引

也是把主关键字拿出来建索引表,但是就是把主关键字分成一个个的大类,比如1-10,10-20等范围


图3

它的时间复杂度分两步,第一步是分块查找,第二步是块内查找(块内一般是无序的,但是可以是有序的),所以如果两步都是采用顺序查找,就发现查找平均长度是根号n加1。比O(n)会快。

算法平均长度:就是一个算法走的步数,然后平均下来的值。大O记法就是平均长度里面的最高项。

倒排索引

倒排索引就是用次关键字建成一张表。次关键字其实就是数据记录里面一些属性值
倒排索引指的是通过属性值来确定数据记录,而正排索引就是说通过数据记录再找到里面的属性值。

通俗来讲,当搜索一个字符串“you”的时候(“you”就是属性值):

1.正排索引的查找算法:
文档1有没有“you”-->文档2有没有“you”-->文档3有没有“you”
(每一个数据记录有没有此属性值)

2.倒排索引的查找算法:
找到“you”-->“you”存在与文档1、2、3
如图3


图3

你可能感兴趣的:(查找——数据的查找(一))