八种排序方法及其性能比较

气泡、快速、插入、希尔、选择、堆、归并、基数排序。


八种排序的原理及其实现:


#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <stdlib.h>
#include <ctime>
#include <algorithm>

using namespace std;

const int maxn=100010;
const int inf=2<<30;

typedef int keytype;

struct records{
    keytype key;
};

typedef records List[maxn];
keytype A[maxn];

void Swap(records &x,records &y){
    records w;
    w=x,x=y,y=w;
}

//冒泡
void Bubble_sort(int n,List &A){
    for(int i=1;i<=n;i++)
        for(int j=n;j>=i+1;j--)
            if(A[j].key < A[j-1].key)
                Swap(A[j],A[j-1]);
}

//快速排序
int  FindPivot( int i, int j,List A) /* 设A是外部数组*/
/*若A[i] A[j]的关键字全部相同,则返回0; 若A[i],…A[j]的关键字全部相同,则返回0;
否则,左边两个不同关键字中的较大者的下标。*/
{
    keytype firstkey = A[i].key ; /* 第1个关键字的值A[i].key*/
    int k ;  /* 从左到右查找不同的关键字*/
    for ( k=i+1 ; k<=j; k++ ) /* 扫描不同的关键字*/
        if ( A[k].key > firstkey ) /* 选择较大的关键字*/
            return k ;
        else if ( A[k].key < firstkey )
            return i ;
    return 0;
}

int Partition( int i , int j , keytype pivot,List A )
/*划分A[i] A[j] 是关键字<i t的在左子序列 划分A[i],…,A[j],是关键字<pivot 的在左子序列,
关键pivot 的在右子序列,返回有子序列的起始下标*/
{
    int l , r;
    do
    {
        for(l=i; A[l].key < pivot ; l++ );
        for(r=j; A[r].key>=pivot ; r--);
        if( l< r) swap(A[l],A[r]);
    }
    while(l <= r);
    return  l;
}

void QuickSort(int i,int j,List &A)
{
    keytype pivot;
    int k; //关键字大于等于pivot的记录在序列中的起始下标 int k; //关键字大于等于pivot的记录在序列中的起始下标
    int pivotindex ; //关键字为pivot的记录在数组A中的下标
    pivotindex=FindPivot(i,j,A);
    if( pivotindex != 0 )   //递归终止条件
    {
        pivot=A[pivotindex].key;
        k=Partition (i,j,pivot,A);
        QuickSort(i,k-1,A);
        QuickSort(k, j,A);
    }
}

//插入排序
void IN_sort(int n,List A){
    int i,j;
    A[0].key=-1;
    for(i=1;i<=n;i++){
        j=i;
        while(A[j].key<A[j-1].key){
            Swap(A[j],A[j-1]);
            j=j-1;
        }
    }
}
//选择排序
void Choose_sort(int n,List A){
    keytype lowkey;
    int lowindex;
    for(int i=1;i<=n;i++){
        lowindex=i;
        lowkey=A[i].key;
        for(int j=i;j<=n;j++){
            if(A[j].key<lowkey){
                lowkey=A[j].key;
                lowindex=j;
            }
        }
        Swap(A[i],A[lowindex]);
    }
}

//希尔排序
void Shell_Sort(int n,List A)
{
    int i, j, d;
    for (d=n/2; d>=1; d=d/2) {
        for (i=d+1; i<=n; i++) { //将A[i]插入到所属的子序列中
            A[0].key= A[i].key; //暂存待插入记录
            j=i-d; //j指向所属子序列的最后一个记录 j=i-d;  //j指向所属子序列的最后 个记录
            while (j>0 && A[0].key< A[j].key) {
                A[j+d]= A[j];//记录后移d个位置 [j ] [j]; 记录后移个位置
                j=j-d; //比较同一子序列的前一个记录
            }
            A[j+d]= A[0];
        }
    }
}

//归并排序
void Merge(int s , int m , int t , List A , List B) /*将有序序列AA和A1A合并为 个有序序列 */ /*将有序序列A[s],…,A[m]和A[m+1],…,A[t]合并为一个有序序列B[s],…,B[t]*/
{
    int i = s ;
    int j = m+1;
    int k = s ;//置初值
    /* 两个序列非空时,取小者输出到B[k]上*/
    while ( i <= m && j <= t )
        B[k++] = ( A[ i ].key <= A[ j ].key) ? A[i++] : A[j++] ;
        /*若第一个子序列非空(未处理完),则复制剩余部分到B*/ /*若第 个子序列非空(未处理完),则复制剩余部分到B */
    while ( i <= m )
        B[k++] = A[i++];
        /*若第二个子序列非空(未处理完) 则复制剩余部分到B*/ /* 若第二个子序列非空(未处理完),则复制剩余部分到B */
    while ( j <= t )
        B[k++] = A[j++];
}

void MergePass(int n , int h , List A , List B)
{
    int i;
    for ( i=1 ; i+2*h-1<= n; i+=2*h)
        Merge(i, i+h-1, i+2*h-1, A, B) ;//归并长度为h的两个有序子序列
    if ( i+h-1< n) /* 尚有两个子序列,其中最后一个长度小于h*/
        Merge( i, i+h-1, n, A, B) ; /* 归并最后两个子序列*/
    else /* 若i<= n且i+h-1>= n时,则剩余一个子序列轮空,直接复制*/
        for (int t= i ; t<= n ; t++ )
            B[t] = A[t] ;
}

void MergeSort(int n,List A){
    int h=1;
    List B;
    while(h<n){
        MergePass(n,h,A,B);
        h=2*h;
        MergePass(n,h,B,A);
        h=2*h;
    }
}

//堆排序
void PushDown(int first,int last,List A){
    int r=first;
    while(r<=last/2){
        if((r==last/2) && (last%2)==0){//r有一个儿子,在2*r
            if(A[r].key>A[2*r].key)
                Swap(A[r],A[2*r]);
            r=last;
        }
        else if((A[r].key>A[2*r].key) && (A[2*r].key<=A[2*r+1].key)){ //与左儿子交换
            Swap(A[r],A[2*r]);
            r=2*r;
        }
        else if((A[r].key>A[2*r].key) && (A[2*r].key>A[2*r+1].key)){ //与右儿子交换
            Swap(A[r],A[2*r+1]);
            r=2*r+1;
        }
        else r=last;
    }
}

void Dui_Sort(int n,List A){
    for(int i=n/2;i>=1;i--)  //建立初始堆(堆逐渐扩大)
        PushDown(i,n,A);
    for(int i=n;i>=2;i--){
        Swap(A[1],A[i]); //根置于末尾
        PushDown(1,i-1,A);
    }
}

#define RADIX_10 10    //整形排序
#define KEYNUM_31 10     //关键字个数,这里为整形位数

int GetNumInPos(int num,int pos)
{
	int temp = 1;
	for (int i = 0; i < pos - 1; i++)
		temp *= 10;

	return (num / temp) % 10;
}

void RadixSort(int* pDataArray, int iDataNum)
{
	int *radixArrays[RADIX_10];    //分别为0~9的序列空间
	for (int i = 0; i < 10; i++)
	{
		radixArrays[i] = (int *)malloc(sizeof(int) * (iDataNum + 1));
		radixArrays[i][0] = 0;    //index为0处记录这组数据的个数
	}

	for (int pos = 1; pos <= KEYNUM_31; pos++)    //从个位开始到31位
	{
		for (int i = 0; i < iDataNum; i++)    //分配过程
		{
			int num = GetNumInPos(pDataArray[i], pos);
			int index = ++radixArrays[num][0];
			radixArrays[num][index] = pDataArray[i];
		}

		for (int i = 0, j =0; i < RADIX_10; i++)    //收集
		{
			for (int k = 1; k <= radixArrays[i][0]; k++)
				pDataArray[j++] = radixArrays[i][k];
			radixArrays[i][0] = 0;    //复位
		}
	}
}

List L1,L2,L3,L4,L5,L6,L7;
int L8[maxn];

int main(){
    int n;
    int x;
    n=maxn;
    for(int i=1;i<=n;i++){
        x=rand()%100010;
        L1[i].key=L2[i].key=L3[i].key=L4[i].key=L5[i].key=L6[i].key=L7[i].key=x;
        L8[i-1]=x;
    }
    double st[10];
    st[1]=clock();
    Bubble_sort(n,L1);
    st[2]=clock();
    IN_sort(n,L2);
    st[3]=clock();
    Choose_sort(n,L3);
    st[4]=clock();
    Shell_Sort(n,L4);
    st[5]=clock();
    MergeSort(n,L5);
    st[6]=clock();
    QuickSort(1,n,L6);
    st[7]=clock();
    Dui_Sort(n,L7);
    st[8]=clock();
    RadixSort(L8,n);
    st[9]=clock();
    printf("Bubble\tIn_sort\t Choose\t  Shell\t  Merge\t  Quick\t Dui_sort\tRadixSort\n");
    for(int i=1;i<=8;i++)
        printf("%lf ",st[i+1]-st[i]);
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值