1.二分查找算法:
输入:顺序表 S(长度为 n),全序关系 ≤(S 是升序的),要查找的元素 u ∈ U
若 n = 0,则返回“没有”
否则
若 n 为奇数,则取 m = (n + 1) / 2
否则,n 为偶数,取 m = n / 2
若 S(m) ≤ u 且 u ≤ S(m) 则
返回“有”
否则,若 S(m) ≤ u 则
按照 ≤ 这个序,二分查找 S 除去前 m 个元素中是否有 u,并返回相应答案
否则,一定是 u ≤ S(m),此时
按照 ≤ 这个序,二分查找 S 前 m - 1 个元素中是否有 u,并返回相应答案
二分查找算法的想法十分简单:在一个升序排列的顺序表中,如果中间的某个元素等于要找的,则已经找到;
如果中间那个元素小于要找的,则要找的只能在中间那个元素之后;
如果中间那个元素大于要找的,则要找的只能在中间那个元素之前。
2.归并排序:
归并排序的时间复杂度为O(nlogn),伪代码如下:
输入:数组 A,全序关系 ≤
(数组下标从 1 开始)
若 A 的长度不超过 1
返回 A
否则
n ← A 的长度
m ← ⎣n / 2⎦
B ← A 的前 m 项组成的数组
C ← n - m 项组成的数组
将 B 归并排序
将 C 归并排序
D ← 空数组
只要 B、C 都不是空数组
如果 B(1) ≤ C(1)
把 B(1) 添加到 D 的最后
从 B 中删除第一项
否则
把 C(1) 添加到 D 的最后
从 C 中删除第一项
把 B 连接到 D 后面
把 C 连接到 D 后面
返回 D
3.平面最近点的分治算法:
时间复杂度为O(nlogn),其伪代码如下:
Solve(S)
调用 Prepare(S)
L ← S 的元素个数
返回 RecursivelySolve(S, 0, L)
Prepare(S)
将 S 按照横坐标升序排序
// 递归求解 S 中 begin(含)到 end(不含)的点
RecursivelySolve(S, begin, end)
若 end - begin ≤ 1
返回 +∞
否则
mid ← ⎣ (begin + end) / 2 ⎦
t ← (S(mid - 1).x + S(mid).x) / 2
δa ← RecursivelySolve(S, begin, mid)
δb ← RecursivelySolve(S, mid, end)
δ ← min { δa, δb }
初始化 B 为空
对 i = mid, ..., end - 1 // 筛选右半边在带状区域内的点
若 S(i).x < t + δ
在 B 的最后追加 S(i)
L ← B 的元素个数
j ← 0
对 i = begin, ..., mid - 1 // 不需要筛选左半边的点
只要 j < L 且 B(j).y < S(i).y - δ 就
j ← j + 1
对 k = j, ..., min { L - 1, j + 5 }
若 |S(i) - B(k)| < δ
δ ← |S(i) - B(k)|
把 S 中 begin(含)到 mid(不含)
和 mid(含)到 end(不含)按照纵坐标升序合并
并存放在 S 的 begin(含)到 end(不含)中
返回 δ
4.计算多项式算法:
输入:复系数多项式 f(x)、g(x)
若 f(x)、g(x) 中一者为 0
输出 0 多项式
m ← f(x)、g(x) 次数中较大者
取 n 为一个合适的、大于 2m + 1 的数
设置 y 为一个 n 维列向量,它的第 k 行是 f(x) 的 k - 1 次项系数(k = 1...n)
设置 z 为一个 n 维列向量,它的第 k 行是 g(x) 的 k - 1 次项系数(k = 1...n)
ŷ ← F(y) // 这里 F 是 Fourier 变换
ẑ ← F(z)
ŵ ← ŷ ⋅ ẑ // 向量逐点乘法
w ← G(ŵ) // 这里 G 是 Fourier 逆变换
令 h(x) 为一个不超过 n - 1 次的多项式,它的 k 次项系数为 w 的第 k + 1 行(k = 0...n - 1)
输出 h(x)