有序数组的查找算法知识点

在计算机的世界里,算法则是指某项操作的过程。4 种主要操作,包括读取、查找、插入和删除。操作可能会有不止一种做法。也就是说,一种操作会有多种算法的实现。

不同的算法能使代码变快或者变慢——高负载时甚至慢到停止工作。

数据结构:有序数组。它的查找算法就不止一种,我们将会学习如何选出正确的那种。

 

有序数组要求其值总是保持有序。即每次插入新值时,它会被插入到适当的位置,使整个数组的值仍然按顺序排列。

常规的数组则并不考虑是否有序,直接把值加到末尾也没问题。
以数组[3,17,80,202]为例。

假设这是个常规的数组,准备将75 插入,那就可以把它放到尾端。计算机只要1 步就能完成这种操作。

但如果这是一个有序数组,你就必须要找到一个适当的位置,使插入75 之后整个数组依然有序。做起来可不像说的那么简单。整个过程不可能一步完成,因为计算机需要先找出那个适当的位置,然后将其及以后的值右移来腾出空间给75。

第1 步:检查索引0 的值,看75 应该在它的左边还是右边。因为75 大于3,所以75 应该在它右边的某个位置。而具体的位置,目前还是不能确定,于是,再检查下一个格子。

第2 步:检查下一格的值。因为75 大于17,所以继续。

第3 步:检查下一格的值。这次是80,大于75。因为这是第一次遇到大于75 的值,可想而知,必须把75 放在80 的左侧以使整个数组维持有序。但要在这里插入75,还得先将它的位置空出来。

第4 步:将最后一个值右移。

第5 步:将倒数第二个值右移。

第6 步:终于可以把75 插入到正确的位置上了。

可以看到,往有序数组中插入新值,需要先做一次查找以确定插入的位置。这是它跟常规数组的关键区别(在性能方面)之一。虽然插入的性能比不上常规数组,但在查找方面,有序数组却有着特殊优势。

常规数组的查找方式:从左至右,逐个格子检查,直至找到。这种方式称为线性查找。
接下来看看有序数组的线性查找跟常规数组有何不同。
设一个常规数组[17,3,75,202,80],如果想在里面查找22(其实并不存在),那你就得逐个元素去检查,因为22 可能在任何一个位置上。要想在到达末尾之前结束检查,那么所找的值必须在末尾之前出现。

然而对于有序数组来说,即便它不包含要找的值,我们也可以提早停止查找。假设要在有序数组[3,17,75,80,202]里查找22,我们可以在查到75 的时候就结束,因为22 不可能出现在75的右边。

有序数组的线性查找大多数情况下都会快于常规数组。除非要找的值是最后那个,或者比最后的值还大,那就只能一直查到最后了。

至今我们提到的查找有序数组的方法就只有线性查找。

但其实,线性查找只不过是查找算法的其中一种而已。这种逐个格子检查直至找到为止的过程,并不是查找的唯一途径。
有序数组相比常规数组的一大优势就是它可以使用另一种查找算法。此种算法名为二分查找,它比线性查找要快得多。

有序数组相比常规数组的一大优势就是它除了可以用线性查找,还可以用二分查找。常规数组因为无序,所以不可能运用二分查找。
假设有一个包含9 个元素的有序数组。计算机不知道每个格子的值。

用二分查找来找出7,过程如下。
第1 步:检查正中间的格子。因为数组的长度是已知的,将长度除以2,我们就可以跳到确切的内存地址上,然后检查其值。值为9,可推测出7 应该在其左边的某个格子里。而且,这下我们也排除了一半的格子,即9 右边的那些(以及9 本身)。

第2 步:检查9 左边的那些格子的最中间那个。因为这里最中间有两个,我们就随便挑了左边的。它的值为4,那么7 就在它的右边了。由此4 左边的格子也就排除了。

第3 步:还剩两个格子里可能有7。我们随便挑个左边的。
第4 步:就剩一个了。(如果还没有,那就说明这个有序数组里真的没有7。)

终于找到7 了,总共4 步。是的,这个有序数组要是用线性查找也会是4 步。

对于长度太小的有序数组,二分查找并不比线性查找好多少。但我们来看看更大的数组。
对于拥有100 个值的数组来说,两种查找需要的最多步数如下所示。
 线性查找:100 步
 二分查找:7 步
用线性查找的话,如果要找的值在最后一个格子,或者比最后一格的值还大,那么就得查遍每个格子。有100 个格子,就是100 步。
二分查找则会在每次猜测后排除掉一半的元素。100 个格子,在第一次猜测后,便排除了50 个。
再换个角度来看,就会发现一个规律。
长度为3 的有序数组,二分查找所需的最多步数是2。
若长度翻倍,变成7(以奇数为例会方便选择正中间的格子,于是我们把长度翻倍后又增加了一个数),则最多步数会是3。
若再翻倍(并加1),变成15 个元素,那么最多步数会是4。

规律就是,每次有序数组长度乘以2,二分查找所需的最多步数只会加1。
这真是出奇地高效。
相反,在3 个元素的数组上线性查找,最多要3 步,7 个元素就最多要7 步,100 个元素就最多要100 步,即元素有多少,最多步数就是多少。

数组长度翻倍,线性查找的最多步数就会翻倍,而二分查找则只是增加1 步。

如果数组变得更大,比如说10 000 个元素,那么线性查找最多会有10 000 步,而二分查找最多只有14 步。再增大到1 000 000 个元素,则线性查找最多有1 000 000 步,二分查找最多只有20 步。
不过还要记住,有序数组并不是所有操作都比常规数组要快。它的插入就相对要慢。

衡量起来,虽然插入是慢了一些,但查找却快了许多。得根据应用场景来判断哪种更合适。

 

猜你喜欢

转载自www.cnblogs.com/lanuj/p/12608074.html