搜索算法
顺序搜索
LINEARSEARCH
输入:n个元素的数组A[1...n]和元素x
输出:如果x = A[j],1≤j≤n,则输出j,否则输出0
1.j = 1
2.while(j < n) and (x ≠ A[j])
3. j = j + 1
4.end while
5.if x = A[j] then return j else return 0
平均查找次数:n/2
二分搜索
BINARYSEARCH
输入:n个元素的升序数组A[1...n]和元素x
输出:如果x = A[j],1≤j≤n,则输出j,否则输出0
1.low = 1, high = n, j = 0
2.while(low ≤ high) and (j = 0)
3. mid = [(low + high) / 2]
4. if x = A[mid] then j = mid
5. else if x < A[mid] then high = mid - 1
6. else low = mid + 1
7.end while
8.return j
该算法最小的比较次数为1,最大的比较次数为[logn]+1
假定x大于等于将要被搜索的序列中的所有元素,根据n为奇数或偶数进行分类讨论。(下列[]均表示向下取整)
- 如果n是偶数,在A[mid+1...n]中的项目数为n/2,否则是(n-1)/2。这两种情况下都有:A[mid+1...n]中元素的个数恰好是[n/2]。
- 类似的,在第三次迭代时,要搜索的剩余元素数目为[[n/2]/2] = [n/4]。
- 一般来说,在while循环中第j次循环时剩余元素的数目是[n/2^(j-1)],或者找到x,或者要搜索的子序列的长度达到1,任何一个条件的满足都使得循环停止执行。结果,搜索x的最大循环次数就是满足条件[n/2^(j-1)] = 1时j的值。
- 根据函数定义,这种情况发生在当
- 1 ≤ n/2^(j-1) < 2
- 2^(j-1) ≤ n < 2^j
- j-1 ≤ logn < j
时。因为j是整数,可以得出结论:j = [logn] + 1。
排序算法
合并两个已排序的表
MERGE
输入:数组A[1...m]和它的三个索引p、q、r,1≤p≤q<r≤m,两个子数组A[p...q]和A[q+1...r]各自按升序排列。
输出:合并两个子数组A[p...q]和A[q+1...r]的数组A[p...r]
1.comment:B[p...r]是个辅助数组
2.s = p,t = q + 1,k = p
3.while s ≤ q and t ≤ r
4. if A[s] ≤ A[t] then
5. B[k] = A[s]
6. s = s + 1
7. else
8. B[k] = A[t]
9. t = t + 1
10. end if
11. k = k + 1
12.end while
13.if s = q + 1 then B[k...r] = A[t...r]
14.else B[k...r] = A[s...q]
15.end if
16.A[p...r] = B[p...r]
若假设执行算法MERGE的两个数组元素个数分别为m、n(m ≤ n),则该算法元素的比较次数在m到m + n - 1之间。元素赋值的次数恰好是2n。
选择排序
SELECTIONSORT
输入:n个元素的数组A[1...n]
输出:按非降序排列的数组A[1...n]
1.for i = 1 to n - 1
2. k = i
3. for j = i + 1 to n ;查找第i小的元素
4. if A[j] < A[k] then k = j
5. end for
6. if k ≠ i then 交换A[i]与A[k]
7.end for
容易看出,这个算法的执行元素比较次数恰好为n(n - 1)/2,也可以看出元素交换的次数介于0 ~ n-1之间。由于每次交换需要3次元素赋值,因此元素赋值的次数介于0 ~ 3(n-1)之间。
插入排序
INSERTIONSORT
输入:n个元素的数组A[1...n]
输出:按非降序排列的数组A[1...n]
1. for i = 2 to n
2. x = A[i]
3. j = i - 1
4. while(j > 0) and (A[j] > x)
5. A[j + 1] = A[j]
6. j = j - 1
7. end while
8. A[j + 1] = x
9.end for
容易看出,当序列已按非降序排列时,元素比较的次数最少,此时元素比较次数为n - 1。当序列已按降序排列,并且所有元素各不相同时,,元素比较的次数最大,这时元素比较的次数是n(n - 1)/2。所以该算法的元素比较次数在n-1 ~ n(n-1)/2之间,元素赋值次数等于元素比较次数加上n - 1。
自底向上合并排序
BOTTOMUPSORT
输入:n个元素的数组A[1...n]
输出:按非降序排列的数组A[1...n]
1.t = 1
2.while t < n
3. s = t,t = 2s,i = 0
4. while i + t ≤ n
5. MERGE(A,i + 1,i + s,i + t) ;分别为数组①上边界,数组①下边界(数组②上边界),数组②下边界
6. i = i + t
7. end while
8. if i + s < n then MERGE(A,i + 1,i + s,n)
9.end while
现在计算当n为2的幂这种特殊情况下,算法执行的元素比较次数:
- 在这种情况下,外部while循环执行k = logn次,排序树中除最顶层外每层执行一次。
- 第一次迭代进行了n/2次比较;在第二次迭代中,n/2个2元素的排序序列被合并成对,每队合并需要的比较次数为2或3(参考MERGE的元素比较次数);在第三次迭代中,n/4个4元素的排序序列被合并成对,每对合并需要的比较次数在4到7之间。
- 由此我们可以得出一般规律:在while循环的第j次迭代中,两个大小为2^(j-1)的子序列的合并操作共有n/(2^j)次,因此,第j次迭代中元素比较的次数在(n/2^j)2^(j-1)到(n/2^j)(2^j - 1)之间。
- 因此,如果令k = logn,那么元素的比较次数最少为:
- 最多为:
- 关于元素赋值次数,在每一次合并操作时观察可知,外部while循环每执行一次需要进行2n次赋值,一共进行了2nlogn次。
综上,当n为2的幂时,元素比较次数在(nlogn)/2到nlogn - n + 1之间。执行该算法的元素赋值次数为2nlogn。