C++算法——排序和搜索

(1)快速排序——分治

注意的是,边界问题特别多,需要背诵一定的模板。先说说该排序的具体思路。

1. 在数组中选一个基准数(通常为数组第一个)

2. 将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边

3. 对于基准数左、右两边的数组,不断重复以上两个过程,直到每个子集只有一个元素,即为全部有序

具体思路参考博客:https://blog.csdn.net/elma_tww/article/details/86164674?biz_id=102&utm_term=%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-86164674&spm=1018.2118.3001.4187

//快排母版,建议全文背诵!!!
void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;//当左右指针相遇的情况

    int i = l - 1, j = r + 1, x = q[l + r >> 1];//这个一定要注意,避免边界问题
    //其中 i = i - 1 和 j = r + 1 是为了检测边界而各退一步
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j)
        {
        	int x = q[i];
        	q[i] = q[j];
        	q[j] = x;
        }
    }
    quick_sort(q, l, j), quick_sort(q, j + 1, r);
}

作者:yxc!!!
链接:https://www.acwing.com/blog/content/277/!!!
来源:AcWing!!!
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。!!!

(2)归并排序——把有序的两个数组归并成一个数组

原理是双指针比较,通过两组有序数组中找出最小值,得到整体的最小值

详细原理请看:https://blog.csdn.net/cqx13763055264/article/details/81701419?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159980784419725222436885%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=159980784419725222436885&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-2-81701419.pc_ecpm_v3_pc_rank_v3&utm_term=%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F&spm=1018.2118.3001.4187

//归并母版,建议全文背诵!!!
const int  N = 1e6 + 10;
int q[N],tmp[N];
using namespace std;

void merge_sort(int q[], int l, int r)
{
    if (l >= r) return;//用于递归,当分到只剩两个元素的时候停止分

    int mid = l + r >> 1;
    merge_sort(q, l, mid);
    merge_sort(q, mid + 1, r);

    int k = 0, i = l, j = mid + 1;//注意这里j是mid+1,防止中间元素重复
    while (i <= mid && j <= r)//这里是两指针进行比较大小
        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];
}
作者:yxc!!!
链接:https://www.acwing.com/blog/content/277/!!!
来源:AcWing!!!
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。!!!

(3)整数二分——主要解决的问题是一段数据中可以分成两部分,并且区分点不重合

注意的是,注意边界,当 r = mid 时, mid不用加一,当 l = mid 时,mid 要加一。

bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

作者:yxc!!!
链接:https://www.acwing.com/blog/content/277/!!!
来源:AcWing!!!
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。!!!
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值