模板代码记录
快速排序:
5
3 1 2 4 5
#include<iostream> using namespace std; void quick_sort(int q[], int l, int r) { /* 1、选取基准值x,确定左右边界 2、i与j分别从左右开始扫描并处理,使得左半区<=x,右半区>=x,直至i、j相遇 3、递归处理左右半区 */ if (l >= r) return; // 区间为空或只有一个数则排序完成 int x = q[(l + r) >> 1]; // 取数组中间位置 int i = l - 1; // 扫描开始时即加一,故先减一 int j = r + 1; // 同上 while (i < j) { do i++; while (q[i] < x); do j--; while (q[j] > x); if (i < j) { // 当i、j各自仍位于其所属半区时,调换i、j指向的值 int t = q[i]; q[i] = q[j]; q[j] = t; } } quick_sort(q, l, j); quick_sort(q, j + 1, r); // 若以i为划分,则需要修改基准值的取法,避免取到边界值导致无限递归 } int main() { int n; cin >> n; int* q = new int[n + 10]; for (int i = 0; i < n; i++) { cin >> q[i]; } quick_sort(q, 0, n - 1); // 数组名,开始下标,结束下标 for (int i = 0; i < n; i++) { cout << q[i] << " "; } delete[] q; return 0; }
归并排序:
5
3 1 2 4 5
#include<iostream> using namespace std; const int N = 1e6; int q[N], tmp[N]; void merge_sort(int q[], int l, int r) { /* 1、将数组从中间切割,分别对其递归处理 2、两段数组依次读取数据,有序存入临时数组 3、将临时数组数据填入原数组[l,r]区间 */ if (l >= r) return; // 若区间为空或只有一个数则完成排序 int mid = (l + r) >> 1; merge_sort(q, l, mid), merge_sort(q, mid + 1, r); int i = l, j = mid + 1, k = 0; // i、j分别指向两段数据的开头 while (i <= mid && j <= r) { // 同时扫描两段区域,将i、j指向的较小的数存入临时数组,并移动i、j if (q[i] <= q[j]) tmp[k++] = q[i++]; else tmp[k++] = q[j++]; } while (i <= mid) tmp[k++] = q[i++]; // 若左半区还剩数据则追加到临时数据末尾 while (j <= r) tmp[k++] = q[j++]; // 同上 for (i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j]; // 将临时数组的数据覆盖至原数组对应区域 } int main() { int n; cin >> n; for (int i = 0; i < n; i++) { cin >> q[i]; } merge_sort(q, 0, n - 1); // 数组名,开始下标,结束下标 for (int i = 0; i < n; i++) { cout << q[i] << " "; } return 0; }
二分查找(整数):
6 3
1 2 2 3 3 4
3
4
5
#include<iostream> using namespace std; const int N = 1e6; int n, q, k, s[N] = { 0 }; int main() { cin >> n >> q; for (int i = 0; i < n; i++) cin >> s[i]; while (q--) { cin >> k; /* 为了方便记忆,可以假设我们希望k的区间尽量大,那么第一次二分的右边界期望左移,第二次二分的左边界期望右移 */ int l = 0, r = n - 1; // 一轮二分 while (l < r) { int mid = (l + r) >> 1; if (s[mid] >= k) r = mid; // 期望右边界缩小 else l = mid + 1; } if (s[l] != k) cout << "-1 -1\n"; // 此时 l==r,验证是否存在k else { cout << l << " "; // 二轮二分 l = 0, r = n - 1; while (l < r) { int mid = (l + r + 1) >> 1;// 注意多加1 if (s[mid] <= k) l = mid; // 期望左边界增大 else r = mid - 1; } cout << l << endl; } } return 0; }