!二分 binary research
伪代码
low = 1,high = n,j = 0;
while(low<=high && j == 0)
{
mid = (low+high)/2 向下取整
if(x = A[mid]) j = mid;
else if(x < A[mid]) high = mid - 1;
else low = mid + 1;
}
//end while;
return j;
算法规模
最多运行次数: ⌊ l o g n ⌋ + 1 \lfloor log n \rfloor + 1 ⌊logn⌋+1
1st round: n
2nd round: ⌊ n / 2 ⌋ \lfloor n/2 \rfloor ⌊n/2⌋
…
!合并两个有序序列
input: A[p…q] and A[q+1…r]
output: A[p…r] are sorted in nondecreasing order
伪代码
s = p, t = q + 1, k = p;
while(s<=q && t<=r)
{
if (A[s] <= A[t])
{
B[k] = A[s];
s++
}
else
{
B[k] = A[t];
t++;
}
}
end while;
if (s = q + 1)
B[k...r] = A[t...r];
else B[k...r] = A[s...q]
end if
A[p...r] = B[p...r]
question
- 最小比较次数 n 1 n_1 n1
- 最大比较次数 n − 1 n-1 n−1
- 元素赋值的最大数量 2 n 2n 2n
- 元素赋值的最小数量 2 n 2n 2n
对于两个规模为 n 1 n_1 n1和 n 2 n_2 n2合并,操作次数在 [ n 1 , n − 1 ] [n_1 , n-1] [n1,n−1]之间
赋值次数为 2 n 2n 2n
!选择排序
首先找最小元素,放在A[1],然后找剩下n-1个元素的最小元素,放到A[2]…直至找到第二大元素放置A[n-1]。
伪代码
for i = 1 to n - 1
k = i
for j = i + 1 to n
if A[j] < A[k] then k = j
end for
if k != i then swap(A[i],A[k])
end for
· 比较次数: n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n−1)
· 交换次数:[0,n-1]
· 每次交换3次元素赋值
插入排序
A[1]
A[2] 插入A[1]前或者后
................
A[i]插入到A[1...i-1]中的合适位置:
以此扫描i-1到1的元素,将A[i]与当前元素比较
截止条件:find a element <= A[i] or all the elements were scaned
伪代码
for i = 2 to n
x = A[i]
j = i - 1
while(j > 0 && A[j] > x)
A[j + 1] = A[j]
j = j - 1
end while
A[j + 1] = x
end for
元素赋值次数:比较次数 + n − 1 +n-1 +n−1
· 当序列已按非降序排列,元素比较次数最小,元素比较次数为 n − 1 n-1 n−1
· 元素降序排列时,并且各元素不同,元素比较次数最大, n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n−1)
插入排序的改进:二分插入排序
在确定插入位置的时候采用二分
归并排序
最少次数: n l o g n 2 \frac{nlogn}{2} 2nlogn
最多次数: n l o g n − n + 1 nlogn - n + 1 nlogn−n+1
对n各元素排序
t = 1;//初始问题规模
while(t < n)//子规模
s = t, t = 2s, i = 0;//t为合并总规模
while(i + t <= n)
merge(A, i + 1, i + s, i + t)
i = i + t
end while
if(i + s < n) merge(A, i + 1, i + s, n)
end while
· l o g n logn logn