ithink.chan 6c4421a457 文件重命名
Signed-off-by: ithink.chan <chenyang@autoai.com>
2019-08-20 14:25:39 +08:00

76 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 4.3 查找与插入算法
在实际应用中,查找数据和插入新数据都是很常见的操作,在本节中可以看到,高效的查找和插入操作都要求数据首先是有序的,这依赖于上一节的排序算法。可以对很多种数据结构实施排序、查找和插入操作,但到本节为止,我们都是以数组为基本结构进行讲解的,其他类型数据结构的排序、查找和插入操作将在各自章节进行说明。
## 4.3.1 顺序查找
顺序查找是最简单的查找方式,假设有一个长度为 N 的数组,只要从数组的第一个元素开始访问,到最后一个元素结束,中间如果遇到了匹配的值,就返回。
```cpp
/*
* @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-插入新数据](img/4-3/4-3-3-001.jpg)
## 练习
某中学级进行了期末考试学生的姓名性别学号(具有唯一性)、年级班级成绩都保存在电脑中实现一个程序
1. 任意给出学号或学生姓名输出对应的学生信息和数学成绩
2. 允许插入新的学生信息和数学成绩