模板代码记录

快速排序:

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;
}
 
posted @ 2021-01-15 09:16  stargazerzzh  阅读(106)  评论(0编辑  收藏  举报