• 快速排序的实现(三种划分元素的实现,双指针


    众所周知,快速排序的核心是分治的思想,选一个基准出来,然后通过划分操作,使得,该元素最终处于的位置的左边的元素都小于等于它,右边的元素都大于等于它

    划分操作就是两次递归嘛,没什么的,关键在于不借助外部空间我们如何实现划分操作

    首先我们不知道该元素放在哪里,显然这是最后才能确定的,

    我了解到一种填坑法的实现...

    那就是首先保存第一个位置的值,然后从后向前扫描第一个小于x的值,我们就可以直接覆盖第一个位置的值,然后我们再从前向后找大于x的值,

    把后面的坑填上

    下面枚举几种情况

    基准前后有相同数量的数

    5 6 7 4 1 2 3

    因为初始化的原因,我们想选4为基准就需要交换5,4

    4 6 7 5 1 2 3

    x=4

    3比4小,覆盖4

    3 6 7 5 1 2 3

    从前往后扫,6比4大,覆盖3

    3 6 7 5 1 2 6

    从后往前扫,2比4小,覆盖6

    3 2 7 5 1 2 6

    从前往后扫,7比4大,覆盖2

    3 2 7 5 1 7 6

    从后往前扫,1比4小,覆盖7

    3 2 1 5 1 7 6

    从前往后扫,5比4大,覆盖1

    3 2 1 5 5 7 6

    前后有不同数量的数

    6 7 4 1 2 3

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int maxn=100005;
    int n,a[maxn];
    // 3 2 8 4 5 3
    // 2 2 8 4 5 3
    // 
    void quick(int l,int r){
        if(l>=r) return;
        int pivot=(l+r)>>1;swap(a[l],a[pivot]);
        int left=l,right=r,x=a[l];
        while(left<right){
            while(right>left&&a[right]>=x)   right--;
            if(right>left) a[left++]=a[right];
            while(left<right&&a[left]<=x)    left++;
            if(left<right) a[right--]=a[left];
        }
        a[left]=x;
        for(int i=0;i<n;++i) printf("%d,",a[i]);printf("
    ");
        quick(l,left-1);quick(left+1,r);
    }
    int main(){
        while(~scanf("%d",&n)){
            for(int i=0;i<n;++i) scanf("%d",&a[i]);
            quick(0,n-1);
            for(int i=0;i<n;++i) printf("%d,",a[i]);printf("
    ");
        }
        return 0;
    }

     但是这个写法并不能AC,即使我们让x=a[l+rand()%(r-l+1)]

    还有一种写法是也是维护两个指针i,j,使得0~i都是小于等于x的数,j~n-1都是大于x的数

    初始i=l-1,j=l;如果碰到小于等于x的数,那么我们让a[j]和a[i+1]交换,因为默认a[i+1]是大于x的,交换后

    j指针悬停的位置仍然是大于x的,如果碰到大于x的数,我们直接移动j指针将该位置加入大于x的集合

    附上代码

    实现时注意将最后一个位置空开,最后将i+1这个分界线与a[r]交换,实现时默认基准是a[r]

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <algorithm>
     4 using namespace std;
     5 const int maxn=1e5+7;
     6 int n,a[maxn];
     7 void quick(int l,int r){
     8     if(l>=r) return ;
     9     int x=a[r],i=l-1;
    10     for(int j=l;j<r;++j){
    11         if(a[j]<=x){
    12             i=i+1;
    13             swap(a[i],a[j]);
    14         }
    15     }
    16     swap(a[i+1],a[r]);
    17     quick(l,i);quick(i+2,r);
    18 }
    19 int main(){
    20     while(~scanf("%d",&n)){
    21         for(int i=0;i<n;++i) scanf("%d",a+i);
    22         quick(0,n-1);printf("%d",a[0]);
    23         for(int i=1;i<n;++i) printf(" %d",a[i]);printf("
    ");
    24     }
    25     return 0;
    26 }

    不过这个仍然不能AC。。。

    所以我又学习了另外一种方法,仍然是维护两个指针i,j,使得0~i是小于等于x的数,j~n-1都是大于等于x的数

    所以如果碰到前面有大于等于x后面有小于等于x的那么我们就可以交换,并且i向后移动,j向前移动,

    因为循环跳出的条件是i>j,那么其实最终j变成了小于等于x的边界,i变成了大于等于x的边界,所以根据这两个边界可以进行递归

    如果i,j在同一位置,相互移动跳出循环,其实并不是后面小于等于x的数和前面大于等于x的数成对的

    如果不是成对的,那么必有一部分数是完全大于或小于x的,那么这一部分一定会让某一指针连续跳跃而不进行交换

    所以这个算法是正确的...附上代码

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <algorithm>
     4 #include <cstdlib>
     5 using namespace std;
     6 const int maxn=1e5+7;
     7 int n,a[maxn];
     8 void quick(int l,int r){
     9     int i=l,j=r,x=a[l+rand()%(r-l+1)];
    10     while(i<=j){
    11         while(a[i]<x) i++;
    12         while(a[j]>x) j--;
    13         if(i<=j){
    14             swap(a[i],a[j]);
    15             i++;j--;
    16         }
    17     }
    18     if(l<j) quick(l,j);
    19     if(i<r) quick(i,r);
    20 }
    21 int main(){
    22     while(~scanf("%d",&n)){
    23         for(int i=0;i<n;++i) scanf("%d",a+i);
    24         quick(0,n-1);printf("%d",a[0]);
    25         for(int i=1;i<n;++i) printf(" %d",a[i]);printf("
    ");
    26     }
    27     return 0;
    28 }

    另外值得一提的是stdio.h比cstdio快

  • 相关阅读:
    Linux Kernel Makefiles Kbuild en
    Android 源码结构分析
    Linux Charger IC 驱动移植总结
    Battery Charging Specification Revision 1.2 中文版本
    OpenCV 3.4.2 Windows系统下的环境搭建(附带opencv_contrib-3.4.2)
    OpenCV 经纬法将鱼眼图像展开
    shell 循环结构
    OpenCV之Mat类使用总结
    shell 条件结构之 if 语句使用总结
    OpenCV Error: Unspecified Error(The Function is not implemented)
  • 原文地址:https://www.cnblogs.com/linkzijun/p/6725584.html
Copyright © 2020-2023  润新知