zoukankan      html  css  js  c++  java
  • 排序

    所有排序默认均为升序。

    一、插入排序

    1.1直接插入排序

    /*
    直接插入排序
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    void InsertSort(int R[],int n){//对R[0..n-1]按递增有序进行直接插入排序
        int i,j;
        int tmp;
        for(i=1;i<n;++i){
            tmp=R[i];
            j=i-1;//从右向左在有序区R[0..i-1]中找R[i]的插入位置
            while(j>=0&&tmp<R[j]){
                R[j+1]=R[j];//将关键字大于R[i].key的元素后移
                --j;
            }
            R[j+1]=tmp;//在j+1处插入R[i]
        }
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        InsertSort(a,10);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    1.2折半插入排序

    /*
    折半插入排序
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    void InsertSort1(int R[],int n){//对R[0..n-1]按递增顺序进行折半插入排序
        int i,j,low,high,mid;
        int tmp;
        for(i=1;i<n;++i){
            tmp=R[i];//将R[i]保存到tmp中
            low=0;
            high=i-1;
            while(low<=high){//在R[low..high]中折半查找有序插入的位置
                mid=(low+high)/2;//取中间位置
                if(tmp<R[mid])high=mid-1;//插入点在左半区
                else low=mid+1;//插入点在右半区
            }
            for(j=i-1;j>=high+1;--j)//元素右移
                R[j+1]=R[j];
            R[high+1]=tmp;//插入
        }
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        InsertSort1(a,10);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    1.3希尔排序

    /*
    希尔排序
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    void ShellSort(int R[],int n){//希尔排序算法
        int i,j,gap;
        int tmp;
        gap=n/2;//增量置初值
        while(gap>0){
            for(i=gap;i<n;++i){//对所有相隔gap位置的元素组采用直接插入排序
                tmp=R[i];
                j=i-gap;
                while(j>=0&&tmp<R[j]){//对相隔gap位置的元素组进行排序
                    R[j+gap]=R[j];
                    j=j-gap;
                }
                R[j+gap]=tmp;
            }
            gap=gap/2;//减小增量
        }
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        ShellSort(a,10);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    二、交换排序

    2.1冒泡排序

    /*
    冒泡排序
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    void BubbleSort(int R[],int n){
        int i,j;
        int tmp;
        for(i=0;i<n-1;++i){
            for(j=n-1;j>i;--j){//比较,找出本趟关键字最小的元素
                if(R[j]<R[j-1]){
                    tmp=R[j];//R[j]与R[j-1]进行交换,将关键字最小的元素前移
                    R[j]=R[j-1];
                    R[j-1]=tmp;
                }
            }
        }
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        BubbleSort(a,10);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code
    /*
    改进的冒泡排序
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    void BubbleSort1(int R[],int n){
        int i,j;
        bool exchange;
        int tmp;
        for(i=0;i<n-1;++i){
            exchange=false;
            for(j=n-1;j>i;--j){//比较,找出关键字最小的元素
                if(R[j]<R[j-1]){
                    tmp=R[j];//R[j]与R[j-1]进行交换,将关键字最小的元素前移
                    R[j]=R[j-1];
                    R[j-1]=tmp;
                    exchange=true;
                }
            }
            if(!exchange)return;//本趟没有发生交换,中途结束算法
        }
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        BubbleSort1(a,10);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    2.2快速排序

    /*
    快速排序
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    void QuickSort(int R[],int s,int t){//对R[s]至R[t]的元素进行快速排序
        int i=s,j=t;
        int tmp;
        if(s<t){//区间内至少存在两个元素的情况
            tmp=R[s];//用区间的第1个元素作为基准
            while(i!=j){//从区间两端交替向中间扫描,直至i=j为止
                while(j>i&&R[j]>=tmp)--j;//从右向左扫描,找第1个小于tmp的R[j]
                R[i]=R[j];//找到这样的R[j],R[i]与R[j]交换
                while(i<j&&R[i]<=tmp)++i;//从左向右扫描,找第1个大于tmp的R[i]
                R[j]=R[i];//找到这样的R[i],R[i]与R[j]交换
            }
            R[i]=tmp;
            QuickSort(R,s,i-1);//对左区间递归排序
            QuickSort(R,i+1,t);//对右区间递归排序
        }
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        QuickSort(a,0,9);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    三、选择排序

    3.1直接选择排序

    /*
    直接选择排序
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    void SelectSort(int R[],int n){
        int i,j,k;
        int tmp;
        for(i=0;i<n-1;++i){//做第i趟排序
            k=i;
            for(j=i+1;j<n;++j){//在当前无序区R[i..n-1]中选最小的R[k]
                if(R[j]<R[k])k=j;//k记下目前找到的最小关键字所在的位置
            }
            if(k!=i){//交换R[i]和R[k]
                tmp=R[i];
                R[i]=R[k];
                R[k]=tmp;
            }
        }
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        SelectSort(a,10);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    3.2堆排序

    /*
    堆排序
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    void sift(int R[],int low,int high){
        int i=low,j=2*i;//R[j]是R[i]的左孩子
        int tmp=R[i];
        while(j<=high){
            if(j<high&&R[j]<R[j+1])++j;//若右孩子较大,把j指向右孩子
            if(tmp<R[j]){
                R[i]=R[j];//将R[j]调整到双亲节点位置上
                i=j;//修改i和j值,以便继续向下筛选
                j=2*i;
            }
            else break;//筛选结束
        }
        R[i]=tmp;//被筛选节点的值放入最终位置
    }
    
    void HeapSort(int R[],int n){
        int i;
        int tmp;
        for(i=n/2;i>=1;--i)sift(R,i,n);//循环建立初始堆
        for(i=n;i>=2;--i){//进行n-1趟堆排序,每一趟堆排序的元素个数减1
            tmp=R[1];//将最后一个元素同当前区间内R[1]对换
            R[1]=R[i];
            R[i]=tmp;
            sift(R,1,i-1);//筛选R[1]节点,得到i-1个节点的堆
        }
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        HeapSort(a,10);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    四、归并排序

    /*
    归并排序
    */
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    
    void Merge(int R[],int low,int mid,int high){
        int *R1;
        int i=low,j=mid+1,k=0;//k是R1的下标,i、j分别为第1、2段的下标
        R1=(int *)malloc((high-low+1)*sizeof(int));//动态分配空间
        while(i<=mid&&j<=high){//在第1段和第2段均未扫描完时循环
            if(R[i]<R[j]){//将第1段中的元素放入R1中
                R1[k]=R[i];
                ++i;
                ++k;
            }
            else{//将第2段中的元素放入R1中
                R1[k]=R[j];
                ++j;
                ++k;
            }
        }
        while(i<=mid){//将第1段余下部分复制到R1中
            R1[k]=R[i];
            ++i;
            ++k;
        }
        while(j<=high){//将第2段余下部分复制到R1中
            R1[k]=R[j];
            ++j;
            ++k;
        }
        for(k=0,i=low;i<=high;++k,++i)//将R1复制回R中
            R[i]=R1[k];
        free(R1);
    }
    
    void MergePass(int R[],int length,int n){//对整个表进行一趟归并
        int i;
        for(i=0;i+2*length-1<n;i=i+2*length)//归并length长的两相邻子表
            Merge(R,i,i+length-1,i+2*length-1);
        if(i+length-1<n)//余下两个子表,后者长度小于length
            Merge(R,i,i+length-1,n-1);//归并这两个子表
    }
    
    void MergeSort(int R[],int n){//自底向上的二路归并算法
        int length;
        for(length=1;length<n;length=2*length)//进行log2(n)趟归并
            MergePass(R,length,n);
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        MergeSort(a,10);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    五、分配排序

    5.1桶排序

    5.2基数排序

    性能:

    排序方法 时间复杂度 空间复杂度 稳定性 复杂性
    平均情况 最坏情况 最好情况
    1.1直接插入排序 O(n^2) O(n^2) O(n) O(1) 稳定 简单
    1.2折半插入排序            
    1.3希尔排序 O(n^1.3)     O(1) 不稳定 较复杂
    2.1冒泡排序 O(n^2) O(n^2) O(n) O(1) 稳定 简单
    2.2快速排序 O(nlog2(n) O(n^2) O(nlog2(n) O(log2(n) 不稳定 较复杂
    3.1直接选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 简单
    3.2堆排序 O(nlog2(n) O(nlog2(n) O(nlog2(n) O(1) 不稳定 较复杂
    4归并排序 O(nlog2(n) O(nlog2(n) O(nlog2(n) O(n) 稳定 较复杂
    5.1桶排序            
    5.2基数排序 O(d(n+r)) O(d(n+r)) O(d(n+r)) O(r) 稳定 较复杂

    然而使用过程中大都直接调用sort,qsort函数,如下:

    一、sort

    头文件:algorithm

    ①sort(首地址,首地址+排序个数);//默认升序

    参数1:首地址

    参数2:尾地址的下一地址

    例:sort(a,b);//表示排序区间为[a,b)

    简单来说,有一个数组int a[100],要对从a[0]到a[99]的元素进行排序,只要写sort(a,a+100);就行了。

    ②sort(首地址,首地址+排序个数,比较函数);//按比较函数进行排序

    比较函数的返回值:The value returned indicates whether the element passed as first argument is considered to go before the second in the specific strict weak ordering it defines.

    1.int

    /*
    sort排序
    int升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        sort(a,a+10);//默认升序
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code
    /*
    sort排序
    int降序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    bool cmp(int a,int b){
        return a>b;//降序
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        sort(a,a+10,cmp);//
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    2.char

    /*
    sort排序
    char升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    int main(){
        char a[]={'5','4','3','2','1','0','9','8','7','6'};
        int i;
        sort(a,a+10);//默认升序
        for(i=0;i<10;++i)
            printf("%c ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code
    /*
    sort排序
    char降序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    bool cmp(char a,char b){
        return a>b;//降序
    }
    
    int main(){
        char a[]={'5','4','3','2','1','0','9','8','7','6'};
        int i;
        sort(a,a+10,cmp);//
        for(i=0;i<10;++i)
            printf("%c ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    3.double

    /*
    sort排序
    double升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    int main(){
        double a[]={5,4,3,2,1,0,9,8,7,6};
        int i;
        sort(a,a+10);//默认升序
        for(i=0;i<10;++i)
            printf("%.2f ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code
    /*
    sort排序
    double降序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    bool cmp(double a,double b){
        return a>b;//降序(估计也有精度问题,需注意。)
    }
    
    int main(){
        double a[]={5,4,3,2,1,0,9,8,7,6};
        int i;
        sort(a,a+10,cmp);//
        for(i=0;i<10;++i)
            printf("%.2f ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    4.结构体

    /*
    sort排序
    结构体排序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    struct node{
        int a;
        int b;
    }a[10];
    
    bool cmp(node a,node b){
        if(a.a!=b.a)return a.a<b.a;//a升
        return a.b>b.b;//b降
    }
    
    int main(){
        a[0].a=a[1].a=a[2].a=5;
        a[0].b=3;a[1].b=2;a[2].b=1;
        a[3].a=a[4].a=a[5].a=0;
        a[3].b=9;a[4].b=8;a[5].b=7;
        int i;
        sort(a,a+6,cmp);//
        for(i=0;i<6;++i)
            printf("%d %d
    ",a[i].a,a[i].b);
        return 0;
    }
    View Code

    5.字符串

     错误代码1:

    /*
    sort排序
    字符串升序,错误
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    int main(){
        char a[4][20]={"cccc","bbbb","bbcccc","aaaaaaa"};
        int i;
        sort(a,a+4);//默认升序
        for(i=0;i<4;++i)
            printf("%s
    ",a[i]);
        return 0;
    }
    View Code

    错误代码2:

    /*
    sort排序
    字符串升序,错误
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    
    bool cmp(char a[],char b[]){
        return strcmp(a,b)<0;//升序
    }
    
    int main(){
        char a[4][20]={"cccc","bbbb","bbcccc","aaaaaaa"};
        int i;
        sort(a,a+4,cmp);//
        for(i=0;i<4;++i)
            printf("%s
    ",a[i]);
        return 0;
    }
    View Code

    正确代码:字符串写到结构体中。

    /*
    sort排序
    字符串升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    
    struct node{
        char a[20];
    }a[4];
    
    bool cmp(node a,node b){
        return strcmp(a.a,b.a)<0;//升序
    }
    
    int main(){
        strcpy(a[0].a,"cccc");
        strcpy(a[1].a,"bbbb");
        strcpy(a[2].a,"bbcccc");
        strcpy(a[3].a,"aaaaaaa");
        int i;
        sort(a,a+4,cmp);//
        for(i=0;i<4;++i)
            printf("%s
    ",a[i].a);
        return 0;
    }
    View Code

    由于cmp是针对于自定义类型node的,所以也可以通过运算符重载来实现排序的方式。

    /*
    sort排序
    字符串升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    
    struct node{
        char a[20];
    }a[4];
    
    bool operator<(node a,node b){
        return strcmp(a.a,b.a)<0;//(即a.a<b.a)升序
    }
    
    int main(){
        strcpy(a[0].a,"cccc");
        strcpy(a[1].a,"bbbb");
        strcpy(a[2].a,"bbcccc");
        strcpy(a[3].a,"aaaaaaa");
        int i;
        sort(a,a+4);//
        for(i=0;i<4;++i)
            printf("%s
    ",a[i].a);
        return 0;
    }
    View Code
    /*
    sort排序
    字符串降序
    */
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    
    struct node{
        char a[20];
    }a[4];
    
    bool operator<(node a,node b){
        return strcmp(a.a,b.a)>0;//(即a.a>b.a)降序
    }
    
    int main(){
        strcpy(a[0].a,"cccc");
        strcpy(a[1].a,"bbbb");
        strcpy(a[2].a,"bbcccc");
        strcpy(a[3].a,"aaaaaaa");
        int i;
        sort(a,a+4);//
        for(i=0;i<4;++i)
            printf("%s
    ",a[i].a);
        return 0;
    }
    View Code

    二、qsort

    头文件:stdlib.h

    qsort(首地址,排序个数,每个元素占用空间大小,比较函数);

    设比较函数:int compar (const void* p1, const void* p2);

    比较函数的返回值:

    return valuemeaning
    <0 The element pointed to by p1 goes before the element pointed to by p2
    0 The element pointed to by p1 is equivalent to the element pointed to by p2
    >0 The element pointed to by p1 goes after the element pointed to by p2



    For types that can be compared using regular relational operators, a general compar function may look like:

    int compareMyType (const void * a, const void * b)
    {
      if ( *(MyType*)a <  *(MyType*)b ) return -1;
      if ( *(MyType*)a == *(MyType*)b ) return 0;
      if ( *(MyType*)a >  *(MyType*)b ) return 1;
    }

    1.int

    /*
    qsort排序
    int升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    
    int cmp(const void *a,const void *b){
        return *(int *)a-*(int *)b;//升序
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        qsort(a,10,sizeof(int),cmp);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code
    /*
    qsort排序
    int升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    
    int cmp(const void *a,const void *b){
        //return *(int *)a-*(int *)b;//升序
        //与下面等价
        int *A=(int *)a;//强制转化
        int *B=(int *)b;
        return *A-*B;
    }
    
    int main(){
        int a[]={5,4,3,2,1,0,9,8,7,6},i;
        qsort(a,10,sizeof(int),cmp);
        for(i=0;i<10;++i)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    2.char

    /*
    qsort排序
    char升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    
    int cmp(const void *a,const void *b){
        return *(char *)a-*(char *)b;//升序
    }
    
    int main(){
        char a[]={'5','4','3','2','1','0','9','8','7','6'};
        int i;
        qsort(a,10,sizeof(char),cmp);
        for(i=0;i<10;++i)
            printf("%c ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    3.double

    /*
    qsort排序
    double升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    
    int cmp(const void *a,const void *b){
        return *(double *)a<*(double *)b?-1:1;//升序
    }
    
    int main(){
        double a[]={5,4,3,2,1,0,9,8,7,6};
        int i;
        qsort(a,10,sizeof(double),cmp);
        for(i=0;i<10;++i)
            printf("%.2f ",a[i]);
        printf("
    ");
        return 0;
    }
    View Code

    4.结构体

    /*
    qsort排序
    结构体排序
    */
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    
    struct node{
        int a;
        int b;
    }a[10];
    
    int cmp(const void *a,const void *b){
        node *A=(node *)a;
        node *B=(node *)b;
        if(A->a!=B->a)return A->a-B->a;//a升
        return B->b-A->b;//b降
    }
    
    int main(){
        a[0].a=a[1].a=a[2].a=5;
        a[0].b=3;a[1].b=2;a[2].b=1;
        a[3].a=a[4].a=a[5].a=0;
        a[3].b=9;a[4].b=8;a[5].b=7;
        int i;
        qsort(a,6,sizeof(node),cmp);
        for(i=0;i<6;++i)
            printf("%d %d
    ",a[i].a,a[i].b);
        return 0;
    }
    View Code

    5.字符串

    /*
    qsort排序
    字符串升序
    */
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    using namespace std;
    
    int cmp(const void *a,const void *b){
        return strcmp((char *)a,(char *)b);//升序
    }
    
    int main(){
        char a[4][20]={"cccc","bbbb","bbcccc","aaaaaaa"};
        int i;
        qsort(a,4,sizeof(a[0]),cmp);
        for(i=0;i<4;++i)
            printf("%s
    ",a[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    Java IO流 简介
    Centos8安装java部署环境
    RedisTemplate
    手把手教windows上安装linux虚拟机及环境配置
    使用Swagger2构建 RESTful API文档
    VMware 安装 Centos 7 虚拟机配置网络
    别再写满屏的 try catch 了
    isEmpty 和 isBlank 的用法区别
    SpringBoot 中必须掌握的45个注解
    数组的栈方法
  • 原文地址:https://www.cnblogs.com/gongpixin/p/5360930.html
Copyright © 2011-2022 走看看