排序算法的比较

快排和归并
1.思想:都使用了分治的思路。归并是先局部有序再组合起来,快排是先大体有序(前半部分小于某个数,后半部分大于某个数)在局部排好。
2.时间复杂度:归并是严格的NlogN;快排平均时间复杂度NlogN(因为标杆的数不一定是在最中间),最坏有可能退化到N^2。
3.空间复杂度:归并需要额外一个空间用来合并,快排可以原地排序。
4.稳定性:快排不稳定,归并可以稳定。

归并排序:

class Solution {
public:
    void sortIntegers2(vector<int> &A) {
       if (A.size()==0 || A.size()==1) return;
       
       vector<int> tmp(A.size(),0);
       mergeSort(A,0,A.size()-1,tmp);
    }
    void mergeSort(vector<int> &A,int start,int end,vector<int> &tmp) {
        if (start>=end) return;
        mergeSort(A,start,(start+end)/2,tmp);
        mergeSort(A,(start+end)/2+1,end,tmp);
        
        //合并
        int index=start;
        int left=start;
        int right=(start+end)/2+1;
        while (left<=(start+end)/2 && right<=end) {
            if (A[left]<=A[right]) {
                tmp[index++]=A[left++];
            }else {
                tmp[index++]=A[right++];
            }
        }
        while (left<=(start+end)/2) tmp[index++]=A[left++];
        while (right<=end) tmp[index++]=A[right++];
        for (int i=start;i<=end;i++)
            A[i]=tmp[i];
    }
};

快排:

class Solution {
public:
    void sortIntegers2(vector<int> &A) {
       if (A.size()==0 || A.size()==1) return;
       
       vector<int> tmp(A.size(),0);
       quickSort(A,0,A.size()-1);
    }
    void quickSort(vector<int> &A,int start,int end) {
        if (start>=end) return;
        //也可以随机取,经验上这样取比较好,如果取首尾很有可能退化成最坏情况
        int pivot=A[(start+end)/2];
        int left=start;
        int right=end;
        //注意有=,否则在[1,2]这种情况会一直分成[1],[1,2],会出错
        while(left<=right){
            //注意第二个条件没有等号,允许等于pivot的数分布在两个部分,尽量使左右两部分数字个数不要相差太多,否则会退化
            while(left<=right && A[left]<pivot) {
                left++;
            }
            while(left<=right && A[right]>pivot) {
                right--;
            }
            if (left<=right) {
                swap(A[left],A[right]);
                left++;
                right--;
            }
        }
        //这时right已经在left左边了
        quickSort(A,start,right);
        quickSort(A,left,end);
    }
};

143. 排颜色 II
如果没有原地排序的要求,可以使用计数排序。原地的话类似快排,只不过pivot不是随机找的而是根据颜色区间定的。由于pivot也是由colorTo和colorFrom定的,所以要注意往两边排序的条件,左边是小于等于,右边是大于。

class Solution {
public:
    void sortColors2(vector<int> &colors, int k) {
        if (colors.size()==0 ||colors.size()==1) return;

        sort(colors,0,colors.size()-1,1,k);
    }
    void sort(vector<int> &colors,int start,int end, 
              int colorsFrom, int colorsTo) {
        if (start>=end || colorsTo==colorsFrom) return;
        
        
        int mid=(colorsTo+colorsFrom)/2;
        int i=start;
        int j=end;
        while (i<=j) {
            //由于mid是取上整,为了避免i左边没有数,应该把等于mid的情况归类到左边;
            while (i<=j && colors[i]<=mid) i++;
            while (i<=j && colors[j]>mid) j--;
            if (i<=j) {
                swap(colors[i],colors[j]);
                i++;
                j--;
            }
        }
        sort(colors,start,j,colorsFrom,mid);
        sort(colors,i,end,mid+1,colorsTo);
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值