各种排序算法

1.冒泡排序

整个排序过程为大的元素不断往后交换,每一轮排序排好一个元素。

class BubbleSort {
public:
    int* bubbleSort(int* A, int n) {
        
        int i=0;
        while(i<n-1)
        {
            int j=0;
            while(j<n-i-1)
            {
                if(A[j]>A[j+1])
                {
                    int t=A[j];
                    A[j]=A[j+1];
                    A[j+1]=t;
                }
                ++j;
            }
            ++i;
        }
        return A;
    }
};

以上代码的while也可以换成for或者混合使用,还可以做一些简单的改进,例如如果发现某一趟排序已经是有序的,则可以结束整个排序过程。

2.选择排序

每轮排序选出一个最小的放在前面正确的位置上。

class SelectionSort {
public:
    int* selectionSort(int* A, int n) {
  
        int i, j, min, tmp;
 
        for (i = 0; i < n - 1; i++)
        {
            min = i;//假设要排的元素的位置就是当前位置
 
            for (j = i + 1; j < n; j++)
                if (A[j] < A[min])
                    min = j;
 
            if (i != min) {
                tmp = A[min];
                A[min] = A[i];
                A[i] = tmp;
            }
        }
        return A;
    }
};

3.插入排序

前面的元素都是有序的,以此把元素加入到前面有序的元素中。

class InsertionSort {
public:
    int* insertionSort(int* A, int n) {
        
        int i=0;
        while (i<n)
        {
            int j=i;
            while((j-1)>=0)
            {
                if(A[j]>A[j-1])
                    break;
                else
                {
                    int t=A[j-1];
                    A[j-1]=A[j];
                    A[j]=t;
                }
                --j;
            }
            ++i;
        }
        return A;
    }
};

4.归并排序

class MergeSort {
    void mergesort2(int A[],int first,int mid,int last,int tmp[])
    {
        int i=first,j=mid+1,k=0;
        while(i<=mid&&j<=last) tmp[k++]=A[i]<=A[j]?A[i++]:A[j++];
        while (i<=mid) tmp[k++]=A[i++];
        while (j<=last) tmp[k++]=A[j++];
        for(i=0;i<k;++i) A[first+i]=tmp[i];
    }
    void mergesort1(int A[],int first,int last,int tmp[])
    {
        if(first<last)
        {
            int mid=(first+last)/2;
            mergesort1(A,first,mid,tmp);//递归
            mergesort1(A,mid+1,last,tmp);
            mergesort2(A,first,mid,last,tmp);//合并
        }
        return;
    }
public:
    int* mergeSort(int* A, int n) {
        
        int* tmp=new int[n];
        if(tmp==NULL) return A;//内存不够用的情况
        mergesort1(A,0,n-1,tmp);
        delete []tmp;
        return A;
    }
};

排序示意图如下:

5.快速排序

每轮排序选择第一个元素为目标元素,比这个元素小的放在它左边,比它大的放在右边。

class QuickSort {
    void quicksort(int A[],int left,int right)
    {
        int i,j,temp;
        if(left>right)
            return;
        temp=A[left];
        i=left;
        j=right;
        
        while(i!=j)
        {
            while(i<j&&A[j]>=temp)
                --j;
            while(i<j&&A[i]<=temp)
                ++i;
            if(i<j)
                swap(A[i],A[j]);
        }
        A[left]=A[i];
        A[i]=temp;
        quicksort(A,left,i-1);
        quicksort(A,i+1,right);
    }
public:
    int* quickSort(int* A, int n) {
       
        quicksort(A,0,n-1);
        return A;
    }
};

例如待排序元素为:

4 5 6 7 8 1 2 3

第一遍排序过程为:

4 5 6 7 8 1 2 3

4 3 6 7 8 1 2 5

4 3 2 7 8 1 6 5

4 3 2 1 8 7 6 5

1 3 2 4 8 7 6 5

6.堆排序

一.非递归方式

class HeapSort {
    void buildheap(int A[],int size)
    {
        int i;
        for(i=size/2-1;i>=0;i--)
        {
            adjustheap(A,i,size);
        }
    }
    
    void adjustheap(int A[],int i,int size)
    {
        int j=i*2+1;//子节点
        while(j<size)
        {
            if(j+1<size&&A[j]<A[j+1]) ++j;
            if(A[i]>A[j]) break;
            swap(A[i],A[j]);
            i=j;
            j=2*i+1;
        }
    }
public:
    int* heapSort(int* A, int n) {
      
        int i;
        buildheap(A,n);
        for(i=n-1;i>=0;i--)
        {
            swap(A[i],A[0]);
            adjustheap(A,0,i);
        }
        return A;
    }
};

二.递归方式

class HeapSort {
public:
    void build_heap(int *tree, int n)
    {
        for (int i = (n - 1)/2; i >= 0; --i) {//从最后一个父节点开始由下往上建堆
            heapify(tree, n, i);
        }
    }
    
    void heapify(int* tree, int n, int i)
    {
        if (i >= n) return; //可以没这个
        
        int c1 = 2 * i + 1;
        int c2 = 2 * i + 2;
        
        int max = i;
        if (c1 < n && tree[c1] > tree[max]) { //一定要判断c1<n,防止越界
            max = c1;
        }
        if (c2 < n && tree[c2] > tree[max]) { //一定要判断c2<n,防止越界
            max = c2;
        }
        if (max != i) {
            swap(tree[max], tree[i]);
            heapify(tree, n, max);
        }
    }
    int* heapSort(int* A, int n) {
        build_heap(A, n);
        for (int i = n - 1; i >= 0; --i) {
            swap(A[0], A[i]);
            //build_heap(A, i);
            heapify(A, i, 0);//i值需要变化
        }
        return A;
    }
};

已知堆上一个节点i,那么它的父节点为(i-1)/2,左孩子为2*i+1,右孩子为2*i+2

7.希尔排序

class ShellSort {
public:
    int* shellSort(int* A, int n) {
        
        int i,j,gap;
        for(gap=n/2;gap>0;gap/=2)
            for(i=gap;i<n;++i)
                for(j=i-gap;j>=0&&A[j]>A[j+gap];j-=gap)
                    swap(A[j],A[j+gap]);
        return A;
    }
};

和冒泡排序比较像,相当于多趟步长不一样的冒泡排序。

8.桶排序

桶排序并不是一种排序算法,而是一种排序思想。包括计数排序,基数排序等。

一.计数排序

class CountingSort {
public:
    int* countingSort(int* A, int n) {
        
        int imax=A[0];
        int imin=A[0];
        for(int i=0;i<n;++i)
        {
            if(A[i]>imax) imax=A[i];
            if(A[i]<imin) imin=A[i];
        }
        int range=imax-imin+1;
        int *count=new int[range];
        memset(count,0,sizeof(int)*range);
        for(int i=0;i<n;++i)
        {
            count[A[i]-imin]++;
        }
        int index=0;
        for(int i=0;i<range;++i)
        {
            while(count[i]--)
            {
                A[index++]=i+imin;//从桶里面倒出来
            }
        }
        delete []count;
        return A;
    }
};

二.基数排序

class RadixSort {
    int maxbit(int A[],int n)
    {
        int b=1;
        int p=10;
        for(int i=0;i<n;++i)
        {
            while(A[i]>=p)
            {
                p*=10;
                ++b;
            }
        }
        return b;
    }
public:
    int* radixSort(int* A, int n) {
       
        int b=maxbit(A,n);
        int *tmp=new int[n];
        int *count=new int[10];
        int i,j,k;
        int radix=1;
        for(i=1;i<=b;++i)
        {
            memset(count,0,sizeof(int)*10);
            for(j=0;j<n;j++)
            {
                k=(A[j]/radix)%10;
                count[k]++;
            }
            for(j=1;j<10;++j)
                count[j]+=count[j-1];//累加起来,数字越大,越靠后
            for(j=n-1;j>=0;j--)
            {
                k=(A[j]/radix)%10;
                tmp[count[k]-1]=A[j];
                count[k]--;
            }
            for(j=0;j<n;j++)
                A[j]=tmp[j];
            radix*=10;
        }
        delete []tmp;
        delete []count;
        return A;
    }
};

9.其他排序相关

一.小范围排序

class ScaleSort {
public:
    void build_heap(int *tree, int k)
    {
        for (int i = (k - 1)/2; i >= 0; --i) {//从最后一个父节点开始由下往上建堆
            heapify(tree, k, i);
        }
    }
    
    void heapify(int* tree, int k, int i)
    {
        if (i >= k) return;
        
        int c1 = 2 * i + 1;
        int c2 = 2 * i + 2;
        
        int min = i;
        if (c1 < k && tree[c1] < tree[min]) {
            min = c1;
        }
        if (c2 < k && tree[c2] < tree[min]) {
            min = c2;
        }
        if (min != i) {
            swap(tree[min], tree[i]);
            heapify(tree, k, min);
        }
    }

    vector<int> sortElement(vector<int> A, int n, int k) {
        int tree[A.size()];
        std::copy(A.begin(), A.end(), tree);
        for (int i = 0; i <= n - k; ++i) {
            build_heap(&tree[i], k);
        }
        for (int i = n-k+1; i < n; ++i) {
            build_heap(&tree[i], --k);
        }
        A.clear();
        for (int i = 0; i < n; ++i)
            A.push_back(tree[i]);
        return A;
    }
};

二.重复值判断

要求空间复杂度为O(1)

static void adjustheap(vector<int>&A,int i,int size)
    {
        int j=i*2+1;//子节点
        while(j<size)
        {
            if(j+1<size&&A[j]<A[j+1]) ++j;
            if(A[i]>A[j]) break;
            swap(A[i],A[j]);
            i=j;
            j=2*i+1;
        }
    }
 void buildheap(vector<int>&A,int size)
    {
        int i;
        for(i=size/2-1;i>=0;i--)
        {
            adjustheap(A,i,size);
        }
    }
void  heapSort(vector<int>&A, int n) {
       
        int i;
        buildheap(A,n);
        for(i=n-1;i>=0;i--)
        {
            swap(A[i],A[0]);
            adjustheap(A,0,i);
        }
    }
class Checker {
public:
    bool checkDuplicate(vector<int> a, int n) {
      
        heapSort(a,n);
        for(int i=1;i<n;++i)
        {
            if(a[i]-a[i-1]==0)
                return true;
        }
        return false;
    }
};

三.合并有序数组

class Merge {
public:
    int* mergeAB(int* A, int* B, int n, int m) {
      
        int i=n-1,j=m-1,k=n+m-1;
        while(i>=0&&j>=0) A[k--]=A[i]>=B[j]?A[i--]:B[j--];
        while(j>=0) A[k--]=B[j--];
        return A;
    }
};

四.三色排序

只有0,1,2三个值元素排序,要求时间复杂度为O(n)

class ThreeColor {
public:
    vector<int> sortThreeColor(vector<int> A, int n) {
       
        int left=-1;
        int right=n;
        int index=0;
        while(index<right){
            if(A[index]==0){
                swap(A,++left,index++);
            }else if(A[index]==2){
                swap(A,index,--right);
            }else{
                index++;
            }
        }
        return A;
    }
    void swap(vector<int> &A,int i,int j){
        int temp=A[i];
        A[i]=A[j];
        A[j]=temp;
    }
};

五.最短子数组

class Subsequence {
public:
    int shortestSubsequence(vector<int> A, int n) {
        
        int max=A[0],left=0;//从左向右正常顺序一直增大,碰见一个小的逆序,记录下来
        int min=A[n-1],right=0;//从右向左正常顺序一直减小,碰见一个大的逆序,记录下来
        int i=0,j=n-1;
        while(i<n)
        {
            if(A[i]>=max)
                max=A[i];
            else
                left=i;
            ++i;
        }
        while(j>=0)
        {
            if(min>=A[j])
                min=A[j];
            else
                right=j;
            --j;
        }
        return (left-right)>0?(left-right+1):0;
    }
};

六.相邻两数最大差值

class Gap {
public:
    int maxGap(vector<int> A, int n) {
        
        if(n<=1)
            return 0;
        int _max=A[0],_min=A[0];
        for(int i=1;i<n;++i)
        {
            if(A[i]>_max)
                _max=A[i];
            else if(A[i]<_min)
                _min=A[i];
        }
        vector<int> ma(n+1,INT_MIN);
        vector<int> mi(n+1,INT_MAX);
        int L=_max-_min;
        int cur;
        for(int i=0;i<n;++i)
        {
            cur=(double)(A[i]-_min)/L*n;
            ma[cur]=max(A[i],ma[cur]);//记录桶里面的最大值
            mi[cur]=min(A[i],mi[cur]);//记录桶里面的最小值
        }
        int res=0;
        int pre=ma[0];
        for(int i=1;i<n+1;++i)
        {
            if(mi[i]!=INT_MAX)
            {
                res=max(res,mi[i]-pre);//记录当前桶的小值与上个桶最大值之间的差值的最大值
                pre=ma[i];
            }
        }
        return res;
    }
};

七.大数据量排序问题

首先要分析待排序数据

(1)数据库

(2)分治法

(3)桶排序,包括位图排序,计数排序等

非稳定排序:快希选堆

参考资料:

用堆处理大数据量的topN问题和排序问题_top-n 堆排序-CSDN博客

https://www.cnblogs.com/Draymonder/p/10698967.html

https://www.cnblogs.com/kex1n/p/7246512.html?utm_source=itdadao&utm_medium=referral

数据量很大的排序问题 大量数据如何排序_大量数据排序-CSDN博客

大数据算法:对5亿数据进行排序-CSDN博客

https://bbs.csdn.net/topics/390360278

排序算法时间复杂度、空间复杂度、稳定性比较_排序算法的时间复杂度和空间复杂度-CSDN博客 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值