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
  • 相关阅读:
    ini_set /ini_get函数功能-----PHP
    【转】那个什么都懂的家伙
    word 2007为不同页插入不同页眉页脚
    August 26th 2017 Week 34th Saturday
    【2017-11-08】Linux与openCV:opencv版本查看及库文件位置等
    August 25th 2017 Week 34th Friday
    August 24th 2017 Week 34th Thursday
    August 23rd 2017 Week 34th Wednesday
    August 22nd 2017 Week 34th Tuesday
    August 21st 2017 Week 34th Monday
  • 原文地址:https://www.cnblogs.com/gongpixin/p/5360930.html
Copyright © 2011-2022 走看看