排序

所有排序默认均为升序。

一、插入排序

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
原文地址:https://www.cnblogs.com/gongpixin/p/5360930.html