lion187 1e03f06795 补充内容。
Signed-off-by: lion187 <cy187lion@sina.com>
2018-12-21 23:58:54 +08:00

4.6 KiB
Raw Blame History

4.3 查找与插入算法

在实际应用中,查找数据和插入新数据都是很常见的操作,在本节中可以看到,高效的查找和插入操作都要求数据首先是有序的,这依赖于上一节的排序算法。可以对很多种数据结构实施排序、查找和插入操作,但到本节为止,我们都是以数组为基本结构进行讲解的,其他类型数据结构的排序、查找和插入操作将在各自章节进行说明。

4.3.1 顺序查找

顺序查找是最简单的查找方式,假设有一个长度为 N 的数组,只要从数组的第一个元素开始访问,到最后一个元素结束,中间如果遇到了匹配的值,就返回。

/*
 * @file main.c
 */
#include <stdio.h>

#define DATA_SIZE   15

int main(void)
{
    int i;
    long find, findidx;
    long data[DATA_SIZE];

    // 读取数据到 data 的代码
    ...

    // 查找数值为 25 的数据
    find = 25;
    findidx = -1;
    for(i=0; i<DATA_SIZE; i++)
    {
        if(find==data[i])
        {
            findidx = (long)i;
            printf("Idx=%d, Val=%d.\n", findidx, data[i]);
            break;
        }
    }
    return 0;
}

最好的情况下,待查找的数据中第一项即为要查找的数据;最坏的情况下,最后一项才是要查找的数据。顺序查找的时间复杂度为 O(N)。

4.3.2 二分查找法

有没有更好的查找法呢?曾经有个猜商品价格的节目,只要猜对价格这个商品就免费送给参与者,嘉宾每次给出一个价格,主持人会告知是高于真实价格还是低于真实价格。如果我们是参与者,如何更迅速的猜对价格呢?假设商品的价格在 0-100¥ 之间,我们可以先尝试下 50¥如果价格低了就试下 75¥如果高于真实价格就猜 62.5¥...

每猜一次,价格范围都能够缩小一半,因此很快就能猜到正确的价格。可以使用类似的思路实现查找算法,称之为二分查找法。用二分查找法查找一个数组的方法如下:

假设数组中有 7 个元素,要查找其中为 'F' 的元素,先从中间的开始找,也就是序号为 3 的元素6/2=3也就是 'D'。但是 D<F因此下次查找 3-6 之间的元素,而 (3+6)/2=4.5,那么我们可以取序号为 4 的元素(向下取整),也可以取序号为 5 的元素(向上取整)。由于向下取整比较容易,因此得到元素 'E',仍然小于 'F',接下来就要查找 4-6 之间的元素,将得到序号为 5 的元素 'F',这就是我们要找的那个。

序号 0 1 2 3 4 5 6
元素 A B C D E F G

如果使用顺序查找算法,需要进行 6 次比较,而使用二分查找法,只需要 3 次,二分查找法的时间复杂度为 O(logN) (以 2 为底 N 的对数),显然,数组越长越能体现二分查找法的优势。

二分查找法之所以有效,是因为以上数组是有序数组,在进行查找时,已经知道了数组是从大到小排序还是从小到大排序的。如果数组是无序的,那么很难知道下一个要找的元素所在位置。因此,要进行快速查找,通常需要对数据进行排序,一般情况下排序只需要进行一次,而查找数据是反复进行的操作,因此为了查找而对数据进行排序是非常有意义的。

4.3.3 插入算法

在实际应用中,插入新数据是很常见的操作。在插入新数据以前,需要先确定要插入的位置,这往往是查找算法的工作。在无序数组中,只能使用顺序查找法,而有序数组中可以使用二分查找法。

在确定了要插入数据的位置后,需要将从插入位置开始到结尾的全部数据向后移动一个位置,将插入的位置空出,之后才能将新数据写入到空出的位置中。

可以看出,在数组中插入新的数据项,往往伴随着旧数据的移动,如果新数据需要插入到末尾,那就是最理想的情况——不需要移动任何数据。但如果新数据需要插入到队首,那就要将原有的 N 个数据都移动一次。下图展示了在数组中定位、移动和插入的具体过程。

4-3-3-001-插入新数据

练习

某中学级进行了期末考试,学生的姓名、性别、学号(具有唯一性)、年级、班级、成绩都保存在电脑中,实现一个程序:

1. 任意给出学号或学生姓名、输出对应的学生信息和数学成绩;
2. 允许插入新的学生信息和数学成绩。