zoukankan      html  css  js  c++  java
  • 快速排序(quick_sort)

    快速排序大体分为三个步骤:

    1.确定分界点 q[(l+r) >> 1] 或者 q[(l+r+1) >> 1] ,两者得看情况而定,不能用 q[l] 或者 q[r] 了 因为会超时。

    2.调整区间范围,让小于等于x的放在左边,大于等于x的数放在右边。

    3.递归处理左右两端。

    模板代码:

    void quick_sort(int q[], int l, int r)
    {
        if(l >= r) return;
        
        int x = q[(l+r) >> 1], i = l-1, j = r+1; //i为左边指针 j为右边指针 确定分界点
        while(i < j) //调整区间
        {
            do i++; while(q[i] < x);
            do j--; while(q[j] > x);
            if(i < j) swap(q[i], q[j]);
        }
    
        quick_sort(q, l, j);
        quick_sort(q, j+1, r);
    }
    

    另外一种

    void quick_sort(int q[], int l, int r)
    {
        if(l >= r) return;
        
        int x = q[l+r+1 >> 1], i = l-1, j = r+1;  //下面i左指针这里就不能用(l+r) >> 1 得取上边界才行 如果下边是右指针 则这里就就只能取下边界
        while(i < j)
        {
            do i++; while(q[i] < x);
            do j--; while(q[j] > x);
            if(i < j) swap(q[i], q[j]);
        }
    
        quick_sort(q, l, i-1);
        quick_sort(q, i, r);
    }
    

    总的来说就是如果x取得是中间两个数得下界 (l+r) >> 1 ,那么下边递归得时候就得是用右指针即 j与j+1 ,如果x取得是中间两个数得上界 (l+r+1) >> 1 ,那么下边递归得时候就得用左指针即 i-1与i ,不然会MLE,即超内存,就是进入了死循环。

    错误代码

    void quick_sort(int q[], int l, int r)
    {
        if(l >= r) return;
        
        int x = q[l+r >> 1], i = l-1, j = r+1;  //下面i左指针这里就不能用(l+r) >> 1 得取上边界才行 如果下边是右指针 则这里就就只能取下边界
        while(i < j)
        {
            do i++; while(q[i] < x);
            do j--; while(q[j] > x);
            if(i < j) swap(q[i], q[j]);
        }
    
        quick_sort(q, l, i-1);
        quick_sort(q, i, r);
    }
    

    用一个样例来说:假如 n=2 ,样例为 1 2 ,最初 i = -1 , j = 2 , x = 1 ,然后进行完 while 循环后, i与j都等于0 ,知识左边区间递归的是0--1,然后根据if(l >= r) return;直接返回结束,然后递归右边区间0--1,这是问题就来了,x仍然是1,继续重复上一个过程,就进入了死循环,所以导致MLE,所以把程序改写成q[(l+r+1) >> 1]即可通过。

    代码

    #include<iostream>
    using namespace std;
    
    const int N = 100010;
    int n;
    int q[N];
    
    void quick_sort(int q[], int l, int r)
    {
        if(l >= r) return;
        
        int x = q[(l+r) >> 1], i = l-1, j = r+1;
        while(i < j)
        {
            do i++; while(q[i] < x);
            do j--; while(q[j] > x);
            if(i < j) swap(q[i], q[j]);
        }
    
        quick_sort(q, l, j);
        quick_sort(q, j+1, r);
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 0; i < n; i++) scanf("%d", &q[i]);
    
        quick_sort(q, 0, n-1);
    
        for(int i = 0; i < n; i++) printf("%d ", q[i]);
        
        system("pause");
        return 0;
    }
    
  • 相关阅读:
    安卓客户端获取手机号码
    安卓自定义控件之设计自己的提示dialog
    一步步打造自己的分页控件4
    C#winform小游戏之贪吃蛇重温C#
    android观察者模式
    Android开发之Java设计模式
    Android 用Animationlist实现逐帧动画
    图片压缩
    Android使用缓存优化ListView
    Android命令行启动程序正确使用技巧解析
  • 原文地址:https://www.cnblogs.com/ZhengLijie/p/13399493.html
Copyright © 2011-2022 走看看