7中排序算法的性能比较

来源:互联网 发布:mysql时间格式 编辑:程序博客网 时间:2024/05/16 12:06
本文转自:C++算法 冒泡排序,快速排序,插入排序,希尔排序,计数排序,基数排序 性能比较

排序是计算机算法中非常重要的一项,而排序算法又有不少实现方法,那么哪些排序算法比较有效率,哪些算法在特定场合比较有效,下面将用C++实现各种算法,并且比较他们的效率,让我们对各种排序有个更深入的了解。

1、冒泡排序
//n^2 冒泡排序V[n]不参与排序void BubbleSort (int V[], int n ) {    bool exchange;     //设置交换标志置    for ( int i = 0; i < n; i++ ){        exchange=false;        for (int j=n-1; j>i; j--) { //反向检测,检查是否逆序            if (V[j-1] > V[j]) //发生逆序,交换相邻元素            {                 int temp=V[j-1];                 V[j-1]=V[j];                V[j]=temp;                 exchange=true;//交换标志置位            }        }                if (exchange == false)            return; //本趟无逆序,停止处理    }}

2、插入排序
//插入排序,L[begin],L[end]都参与排序void InsertionSort ( int L[], const int begin, const int end){    //按关键码 Key 非递减顺序对表进行排序    int temp;    int i, j;    for ( i = begin; i < end; i++ )     {        if (L[i]>L[i+1])         {            temp = L[i+1];             j=i;            do             {                L[j+1]=L[j];                if(j == 0)                {                    j--;                    break;                }                j--;                            } while(temp<L[j]);            L[j+1]=temp;        }    }}

3、快速排序
//n*logn//快速排序A[startingsub],A[endingsub]都参与排序void QuickSort( int A[], int startingsub, int endingsub){    if ( startingsub >= endingsub )        ;    else{        int partition;        int q = startingsub;        int p = endingsub;        int hold;                do{            for(partition = q ; p > q ; p--){                if( A[q] > A[p]){                    hold = A[q];                    A[q] = A[p];                    A[p] = hold;                    break;                }            }            for(partition = p; p > q; q++){                if(A[p] < A[q]){                    hold = A[q];                    A[q] = A[p];                    A[p] = hold;                    break;                }            }                    }while( q < p );        QuickSort( A, startingsub, partition - 1 );        QuickSort( A, partition + 1, endingsub );    }}

4、希尔排序
//希尔排序,L[left],L[right]都参与排序void Shellsort( int L[], const int left, const int right){    int i, j, gap=right-left+1; //增量的初始值    int temp;    do{        gap=gap/3+1; //求下一增量值        for(i=left+gap; i<=right; i++)            //各子序列交替处理            if( L[i]<L[i-gap]){ //逆序                temp=L[i]; j=i-gap;                 do{                    L[j+gap]=L[j]; //后移元素                    j=j-gap; //再比较前一元素                }while(j>left&&temp<L[j]);                L[j+gap]=temp; //将vector[i]回送            }    }while(gap>1);}

5、计数排序
//n//计数排序,L[n]不参与排序void CountingSort( int L[], const int n ){    int i,j;    const int k =1001;    int tmp[k];    int *R;    R = new int[n];    for(i=0;i<k;i++) tmp[i]= 0;     for(j=0;j<n;j++) tmp[L[j]]++;     //执行完上面的循环后,tmp[i]的值是L中等于i的元素的个数    for(i=1;i<k;i++)        tmp[i]=tmp[i]+tmp[i-1]; //执行完上面的循环后,    //tmp[i]的值是L中小于等于i的元素的个数    for(j=n-1;j>=0;j--) //这里是逆向遍历,保证了排序的稳定性    {                R[tmp[L[j]]-1] = L[j];         //L[j]存放在输出数组R的第tmp[L[j]]个位置上        tmp[L[j]]--;         //tmp[L[j]]表示L中剩余的元素中小于等于L[j]的元素的个数             }    for(j=0;j<n;j++) L[j] = R[j];}

6、基数排序
//基数排序void printArray( const int Array[], const int arraySize );int getDigit(int num, int dig);const int radix=10; //基数void RadixSort(int L[], int left, int right, int d){//MSD排序算法的实现。从高位到低位对序列划分,实现排序。d是第几位数,d=1是最低位。left和right是待排序元素子序列的始端与尾端。   int i, j, count[radix], p1, p2;   int *auxArray;   int M = 5;   auxArray = new int[right-left+1];   if (d<=0) return; //位数处理完递归结束   if (right-left+1<M){//对于小序列可调用直接插入排序       InsertionSort(L,left,right); return;   }   for (j=0; j<radix; j++) count[j]=0;   for (i=left; i<=right; i++) //统计各桶元素的存放位置       count[getDigit(L[i],d)]++;   for (j=1; j<radix; j++) //安排各桶元素的存放位置       count[j]=count[j]+count[j-1];   for (i=right; i>=left; i--){ //将待排序序列中的元素按位置分配到各个桶中,存于助数组auxArray中       j=getDigit(L[i],d); //取元素L[i]第d位的值       auxArray[count[j]-1]=L[i]; //按预先计算位置存放       count[j]--; //计数器减1   }   for (i=left, j=0; i<=right; i++, j++)           L[i]=auxArray[j]; //从辅助数组顺序写入原数组   delete []auxArray;    for (j=0; j<radix; j++){ //按桶递归对d-1位处理       p1=count[j]+left; //取桶始端,相对位置,需要加上初值$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$       (j+1 <radix )?(p2=count[j+1]-1+left):(p2=right) ; //取桶尾端     // delete []count;     if(p1<p2){       RadixSort(L, p1, p2, d-1); //对桶内元素进行基数排序      // printArray(L,10);     }   } } int getDigit(int num, int dig){    int myradix = 1;/*    for(int i = 1;i<dig;i++)    {    myradix *= radix;    }*/    switch(dig)    {    case 1:        myradix = 1;        break;case 2:        myradix = 10;        break;case 3:        myradix = 1000;        break;case 4:        myradix = 10000;        break;default:        myradix = 1;        break;    }    return (num/myradix)%radix;}

7、堆排序
//使用时注意将关键码加入#ifndef MINHEAP_H#define MINHEAP_H#include <assert.h>#include <iostream>using std::cout;using std::cin;using std::endl;using std::cerr;#include <stdlib.h>//const int maxPQSize = 50; template <class Type> class MinHeap {public:     MinHeap ( int maxSize );//根据最大长度建堆    MinHeap ( Type arr[], int n );//根据数组arr[]建堆    ~MinHeap ( ) { delete [] heap; }    const MinHeap<Type> & operator = ( const MinHeap &R );//重载赋值运算符    int Insert ( const Type &x );//插入元素    int RemoveMin ( Type &x );//移除关键码最小的元素,并赋给x    int IsEmpty ( ) const { return CurrentSize == 0; }//检查堆是否为空     int IsFull ( ) const { return CurrentSize == MaxHeapSize; }//检查对是否满    void MakeEmpty ( ) { CurrentSize = 0; }//使堆空private:     enum { DefaultSize = 50 };//默认堆的大小    Type *heap;     int CurrentSize;    int MaxHeapSize;    void FilterDown ( int i, int m );//自上向下调整堆    void FilterUp ( int i );//自下向上调整堆};template <class Type> MinHeap <Type>::MinHeap ( int maxSize ){    //根据给定大小maxSize,建立堆对象    MaxHeapSize = (DefaultSize < maxSize ) ? maxSize : DefaultSize;     //确定堆大小    heap = new Type [MaxHeapSize]; //创建堆空间    CurrentSize = 0; //初始化}template <class Type> MinHeap <Type>::MinHeap ( Type arr[], int n ){    //根据给定数组中的数据和大小,建立堆对象     MaxHeapSize = DefaultSize < n ? n : DefaultSize;    heap = new Type [MaxHeapSize];     if(heap==NULL){cerr <<"fail" <<endl;exit(1);}    for(int i =0; i< n; i++)        heap[i] = arr[i]; //数组传送    CurrentSize = n; //当前堆大小    int currentPos = (CurrentSize-2)/2; //最后非叶    while ( currentPos >= 0 ) {         //从下到上逐步扩大,形成堆        FilterDown ( currentPos, CurrentSize-1 );        currentPos-- ;        //从currentPos开始,到0为止, 调整currentPos--; }    }}template <class Type> void MinHeap<Type>::FilterDown ( const int start, const int EndOfHeap ){    // 结点i的左、右子树均为堆,调整结点i    int i = start, j = 2*i+1; // j 是 i 的左子女    Type temp = heap[i];    while ( j <= EndOfHeap ) {        if ( j < EndOfHeap && heap[j] > heap[j+1] )            j++;//两子女中选小者        if ( temp<= heap[j] ) break;        else { heap[i] = heap[j]; i = j; j = 2*j+1; }    }    heap[i] = temp;}template <class Type> int MinHeap<Type>::Insert ( const Type &x ) {    //在堆中插入新元素 x    if ( CurrentSize == MaxHeapSize ) //堆满    {         cout << "堆已满" << endl; return 0;     }    heap[CurrentSize] = x; //插在表尾     FilterUp (CurrentSize); //向上调整为堆    CurrentSize++; //堆元素增一    return 1;}template <class Type> void MinHeap<Type>::FilterUp ( int start ) {    //从 start 开始,向上直到0,调整堆    int j = start, i = (j-1)/2; // i 是 j 的双亲    Type temp = heap[j];    while ( j > 0 ) {         if ( (heap[i].root->data.key )<= (temp.root->data.key) ) break;        else { heap[j] = heap[i]; j = i; i = (i -1)/2; }    }    heap[j] = temp;}template <class Type> int MinHeap <Type>::RemoveMin ( Type &x ) {    if ( !CurrentSize )    {         cout << "堆已空 " << endl;         return 0;     }    x = heap[0]; //最小元素出队列    heap[0] = heap[CurrentSize-1];     CurrentSize--; //用最小元素填补    FilterDown ( 0, CurrentSize-1 );    //从0号位置开始自顶向下调整为堆    return 1;}    #endif

性能测试程序:
#include<iostream>using std::cout;using std::cin;using std::endl;#include <cstdlib>#include <ctime>#include<iostream>using std::cout;using std::cin;using std::ios;using std::cerr;using std::endl;#include<iomanip>using std::setw;using std::fixed;#include<fstream>using std::ifstream;using std::ofstream;using std::flush;#include<string>using std::string;#include <stdio.h>#include <stdlib.h>#include <time.h>#include"minheap.h"void BubbleSort(int arr[], int size);//冒泡排序void QuickSort( int A[], int startingsub, int endingsub);//快速排序void InsertionSort ( int L[], const int begin,const int n);//插入排序void Shellsort( int L[], const int left, const int right);//希尔排序void CountingSort( int L[], const int n );//计数排序int getDigit(int num, int dig);//基数排序中获取第dig位的数字void RadixSort(int L[], int left, int right, int d);//基数排序void printArray( const int Array[], const int arraySize );//输出数组int main(){    clock_t start, finish;    double duration;    /* 测量一个事件持续的时间*/    ofstream *ofs;    string fileName = "sortResult.txt";    ofs = new ofstream(fileName.c_str(),ios::out|ios::app);    const int size = 100000;    int a[size];    int b[size];    srand(time(0));    ofs->close();    for(int i = 0; i < 20;i++)    {        ofs->open(fileName.c_str(),ios::out|ios::app);        if( ofs->fail()){                cout<<"!!";                ofs->close();        }        for(int k =0; k <size;k++)        {            a[k] = rand()%1000;            b[k] = a[k];                    }                 /*    for( k =0; k <size;k++)        {        a[k] = k;        b[k] = a[k];            } */        //printArray(a,size);            //计数排序        for( k =0; k <size;k++)        {            a[k] =     b[k];        }        start = clock();        CountingSort(a,size);                finish = clock();        //    printArray(a,size);                duration = (double)(finish - start) / CLOCKS_PER_SEC;        printf( "%s%f secondsn", "计数排序:",duration );        *ofs<<"第"<<i<<"次:n " <<"排序内容:0~999共" << size << " 个整数n" ;        *ofs<<"第"<<i<<"次计数排序:n " <<"        Time:    " <<fixed<< duration << " secondsn";        //基数排序        for( k =0; k <size;k++)        {            a[k] =     b[k];        }        start = clock();        RadixSort(a, 0,size-1, 3);        finish = clock();        //    printArray(a,size);                duration = (double)(finish - start) / CLOCKS_PER_SEC;        printf( "%s%f secondsn", "基数排序:",duration );        *ofs<<"第"<<i<<"次基数排序:n " <<"        Time:    " << duration << " secondsn";        //堆排序        MinHeap<int> mhp(a,size);         start = clock();        for( k =0; k <size;k++)        {            mhp.RemoveMin(a[k]);        }        finish = clock();        //    printArray(a,size);        duration = (double)(finish - start) / CLOCKS_PER_SEC;        printf( "%s%f secondsn", "堆排序:",duration );        *ofs<<"第"<<i<<"次堆排序:n " <<"        Time:    " << duration << " secondsn";        //快速排序        for( k =0; k <size;k++)        {            a[k] =     b[k];                    }        //printArray(a,size);        start = clock();        QuickSort(a,0,size-1);        finish = clock();        //    printArray(a,size);        duration = (double)(finish - start) / CLOCKS_PER_SEC;        printf( "%s%f secondsn", "快速排序:",duration );        *ofs<<"第"<<i<<"次快速排序:n " <<"        Time:    " << duration << " secondsn";        //希尔排序        for( k =0; k <size;k++)        {            a[k] =     b[k];        }        start = clock();        Shellsort(a,0,size-1);                finish = clock();        //    printArray(a,size);                duration = (double)(finish - start) / CLOCKS_PER_SEC;        printf( "%s%f secondsn", "希尔排序:",duration );        *ofs<<"第"<<i<<"次希尔排序:n " <<"        Time:    " << duration << " secondsn";                //插入排序        for( k =0; k <size;k++)        {            a[k] =     b[k];        }        start = clock();        InsertionSort (a,0,size-1);        finish = clock();        //    printArray(a,size);                duration = (double)(finish - start) / CLOCKS_PER_SEC;        printf( "%s%f secondsn", "插入排序:",duration );        *ofs<<"第"<<i<<"次插入排序:n " <<"        Time:    " << duration << " secondsn";        //冒泡排序        for( k =0; k <size;k++)        {            a[k] =     b[k];        }        start = clock();        BubbleSort(a,size);        finish = clock();        //    printArray(a,size);                duration = (double)(finish - start) / CLOCKS_PER_SEC;        printf( "%s%f secondsn", "冒泡排序:",duration );        *ofs<<"第"<<i<<"次冒泡排序:n " <<"        Time:    " << duration << " secondsn";        ofs->close();        }        return 0;}void printArray( const int Array[], const int arraySize ){    for( int i = 0; i < arraySize; i++ ) {        cout << Array[ i ] << " ";        if ( i % 20 == 19 )            cout << endl;    }    cout << endl;}

性能仿真:
(排序内容:从0~999中随机产生,共100000 个整数,该表中单位为秒)

原创粉丝点击