数据结构知识整理 - 折半查找

版权声明: https://blog.csdn.net/Ha1f_Awake/article/details/85301495

主要内容


 

基本概念

在介绍查找算法前我们先重温几个重要概念

1)数据客观事物的符号表示,是所有能输入到计算机中,并能被计算机程序处理的符号的总称。如数学计算中用到的整数实数,文本编辑中用到的字符串,多媒体程序处理的图形图像声音动画等通过特殊编码定义后的数据。

2)数据元素数据的基本单位,在计算机中通常作为一个整体进行考虑和处理。数据元素也称记录,用于描述一个完整的对象,该对象可以是一名学生的信息(记录),某一次棋局,图中的某一个顶点等。

3)数据项组成数据元素的、有独立含义的、不可分割的最小单位。如学生记录中的学号、姓名、性别等都属于数据项。

4)数据结构相互之间存在一种或多种特定关系的数据元素的集合。数据结构包括逻辑结构(逻辑表示)和存储结构(物理实现)。

5)查找表同一类型的数据元素(或记录)构成的集合,可以由线性表、树结构等多种数据结构来实现。

6)关键字数据元素(或记录)中的某个数据项的值,相当于“数据库”知识中一行记录的主码(PRIMARY KEY)。

typedef struct          /*定义数据元素结构体*/
{
    KeyType key;        /*关键字*/
    OtherType other;    /*其他数据项*/
} Element;


typedef struct          /*以顺序表结构定义查询表*/
{
    /*顺序表借助数组存储数据,因此需要空间基地址base(数组头)和当前长度length(数组长度)*/
    Element *base;      
    int length;
} SSTable;              /*SSTable表示顺序查询表*/

7)查找根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。同样可以类比数据库的数据查询针对不同的数据结构,查找算法也会有所不同。

8)平均查找长度衡量查找算法性能的一个标准。


在查找表的数据结构中,线性表是最简单的一种。

线性表查找又分为顺序查找折半查找分块查找

折半查找(Binary Search)

顾名思义,折半查找每一次查找比较都能使查找范围缩小一半,它是一种效率较高的查找方法。

但是折半查找要求线性表必须采用顺序存储结构,而且表中元素必须按关键字有序排列(有点类似数据库的索引)。

为了标记出查找范围,我们要设置三个变量low、high、middle分别表示查找范围的下界、上界和中间位置(每次查找后更新赋值)。

提前路过的圈毛君:“总是一不留心就把“查找”写成了“查询”(数据库留下的习惯),虽然这两个词意思一样,但无奈博主是强迫症_(:з」∠)_喜欢维持前后文的用词一致性。”

下面给出非递归算法的代码:

int Bin_Search(SSTable t, KeyType key)
{
    int low = 1, high = t.length;
    
    while(low <= high)
    {
        int mid = (low + high) / 2;    

        if(t.base[mid] == key) return mid;

        else if(t.base[mid] < key) low = mid+1;
    
        else high = mid-1;
    }

    return 0;
}

在每次循环中,low、high、mid中的其中两个值都要作更新,而且这个不断缩小查找范围的过程也很像一个不断深入、细化的树或图的遍历过程,因此我们很容易想到一个词——递归

下面给出折半查找的递归算法的实现:

int Bin_Search(SSTable t, KeyType key, int low, int high)
{
    if(low <= high)
    {
        int mid = (low + high) / 2;
        if(t.base[mid] == key) return mid;
        else if(t.base[mid] < key) low = mid + 1;
        else high = mid-1;
    }

    Bin_Search(t, key, low, high);
}

折半查找过程可用二叉树来描述,由此得到的二叉树称为判定树。借助判定树可以很快求出折半查找的平均查找长度。

优点

查找效率比顺序查找高,时间复杂度为O(log2n)。

缺点:

只适用于顺序存储结构的有序表,所以查找前必须先对表进行排序,而排序本身就是一种费时的运算。而且,对于有序表并不方便进行插入、删除操作,因此折半查找不适用于数据元素经常发生变动的查询表。

猜你喜欢

转载自blog.csdn.net/Ha1f_Awake/article/details/85301495