堆排
inline int lson(int i) {
return i << 1;
}
inline int rson(int i) {
return (i << 1) | 1;
}
void msort(int arr[], int n) {
// 1. 建最大堆
for (int i = n / 2; i; i--) {
int l = lson(i), r = min(rson(i), n);
if (arr[i] < arr[l]) swap(arr[i], arr[l]);
if (arr[i] < arr[r]) swap(arr[i], arr[r]);
}
// 2. 每次将最大值和未排序的最后一个元素交换,再 shiftdown
while (n) {
swap(arr[1], arr[n--]);
for (int i = 1; i * 2 <= n; ) {
int l = lson(i), r = min(rson(i), n), pos = arr[l] > arr[r] ? l : r;
if (arr[i] >= arr[pos]) break;
swap(arr[i], arr[pos]);
swap(i, pos);
}
}
}
快排
int tow_partion(int arr[], int l, int r) {
int pos = l + rand() % (r - l + 1), x = arr[pos]; // 随机一个基准
swap(arr[l], arr[pos]);
while (l < r) {
while (r > l && arr[r] >= x) r--;
swap(arr[l], arr[r]);
while (l < r && arr[l] <= x) l++;
swap(arr[l], arr[r]);
}
arr[l] = x;
return l;
}
int three_partion(int arr[], int len) {
int pivot = arr[rand() % len];
// i 代表当前正在处理的元素
// j 代表第一个等于 pivot 的元素
// k 代表第一个大于 pivot 的元素
int i = 0, j = 0, k = len;
while (i < k) {
if (arr[i] < pivot)
swap(arr[i++], arr[j++]);
else if (arr[i] > pivot)
swap(arr[i], arr[--k]);
else
i++;
}
// 将 arr[] 分为了三部分: |--- 小于 pivot ---|---等于pivot---|---大于pivot---|
}
非递归快排
拿队列模拟的时候有点儿像树的层序遍历
int partion(int arr[], int len) {
int pos = rand() % len, pivot = arr[pos];
swap(arr[0], arr[pos]);
int l = 0, r = len - 1;
while (l < r) {
while (r > l && arr[r] > pivot) r--;
swap(arr[l], arr[r]);
while (r > l && arr[l] <= pivot) l++;
swap(arr[l], arr[r]);
}
arr[l] = pivot;
return l;
}
void quick_sort(int arr[], int len) {
queue<pair<int*, int>> q;
q.push({arr, len});
while (!q.empty()) {
pair<int*, int> tp = q.front();
q.pop();
if (tp.second <= 1) continue;
int pos = partion(tp.first, tp.second);
q.push({tp.first, pos});
q.push({tp.first + pos + 1, tp.second - pos - 1});
}
}
KMP
只需要注意 n e x t [ ] next[] next[]的含义
- n e x t [ i ] next[i] next[i]表示 i i i 之前的字符串的最长公共前缀后缀,很巧妙的是,如果在 i i i 位置失配,那么下一个匹配位置是 n e x t [ i ] next[i] next[i]
const int maxn = 1000005;
int nex[maxn];
void ini_nex(string& s) {
int n = s.size();
nex[0] = -1;
int i = 0, j = -1;
while (i < n) {
if (j == -1 || s[i] == s[j]) {
i++, j++;
nex[i] = j;
}
else {
j = nex[j];
}
}
}