• 各种排序算法的C++实现


      这篇文章的源码是大二时数据结构课的实验。当时的实验目的是比较各种排序算法的性能。现在感觉其中的排序源码还比较有用,就贴出来了。

      minheap.h 用于堆排序

    //使用时注意将关键码加入
    #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
    

    sort.cpp 主要的排序函数集包括冒泡排序、快速排序、插入排序、希尔排序、计数排序

    //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; //本趟无逆序,停止处理
    	}
    }
    
    
    
    //插入排序,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;
    		}
    	}
    }
    //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 );
    	}
    }
    
    //希尔排序,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);
    } 
    
    //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];
    }
    
    //基数排序
    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;
    }
    

    maintest.cpp 测试例子

    #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 seconds\n", "计数排序:",duration );
    		*ofs<<"第"<<i<<"次:\n " <<"排序内容:0~999共" << size <<  " 个整数\n" ;
    		*ofs<<"第"<<i<<"次计数排序:\n " <<"		Time:	" <<fixed<< duration <<  " seconds\n";
    		//基数排序
    		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 seconds\n", "基数排序:",duration );
    		*ofs<<"第"<<i<<"次基数排序:\n " <<"		Time:	" << duration <<  " seconds\n";
    		//堆排序
    		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 seconds\n", "堆排序:",duration );
    		*ofs<<"第"<<i<<"次堆排序:\n " <<"		Time:	" << duration <<  " seconds\n";
    		//快速排序
    		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 seconds\n", "快速排序:",duration );
    		*ofs<<"第"<<i<<"次快速排序:\n " <<"		Time:	" << duration <<  " seconds\n";
    
    		//希尔排序
    		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 seconds\n", "希尔排序:",duration );
    		*ofs<<"第"<<i<<"次希尔排序:\n " <<"		Time:	" << duration <<  " seconds\n";
    		
    		//插入排序
    		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 seconds\n", "插入排序:",duration );
    		*ofs<<"第"<<i<<"次插入排序:\n " <<"		Time:	" << duration <<  " seconds\n";
    		//冒泡排序
    		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 seconds\n", "冒泡排序:",duration );
    		*ofs<<"第"<<i<<"次冒泡排序:\n " <<"		Time:	" << duration <<  " seconds\n";
    
    		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 个整数,该表中单位为秒

    次数

    计数排序

    基数排序

    堆排序

    快速排序

    希尔排序

    直接插入排序

    冒泡排序

    1

    0.0000

    0.0310

    0.0470

    0.0470

    0.0310

    14.7970

    58.0930

    2

    0.0000

    0.0470

    0.0310

    0.0470

    0.0470

    16.2500

    53.3280

    3

    0.0000

    0.0310

    0.0310

    0.0310

    0.0310

    14.4850

    62.4380

    4

    0.0000

    0.0320

    0.0320

    0.0470

    0.0310

    17.1090

    61.8440

    5

    0.0000

    0.0310

    0.0470

    0.0470

    0.0310

    16.9380

    62.3280

    6

    0.0000

    0.0310

    0.0310

    0.0470

    0.0310

    16.9380

    57.7030

    7

    0.0000

    0.0310

    0.0470

    0.0310

    0.0310

    16.8750

    61.9380

    8

    0.0150

    0.0470

    0.0310

    0.0470

    0.0320

    17.3910

    62.8600

    9

    0.0000

    0.0320

    0.0470

    0.0460

    0.0310

    16.9530

    62.2660

    10

    0.0000

    0.0470

    0.0310

    0.0470

    0.0310

    17.0160

    60.1410

    11

    0.0000

    0.0930

    0.0780

    0.0320

    0.0310

    14.6090

    54.6570

    12

    0.0000

    0.0310

    0.0320

    0.0310

    0.0310

    15.0940

    62.3430

    13

    0.0000

    0.0310

    0.0310

    0.0470

    0.0310

    17.2340

    61.9530

    14

    0.0000

    0.0320

    0.0470

    0.0470

    0.0310

    16.9060

    61.0620

    15

    0.0000

    0.0320

    0.0320

    0.0460

    0.0320

    16.7810

    62.5310

    16

    0.0000

    0.0470

    0.0470

    0.0620

    0.0310

    17.2350

    57.1720

    17

    0.0150

    0.0160

    0.0320

    0.0470

    0.0310

    14.1400

    52.0320

    18

    0.0150

    0.0160

    0.0310

    0.0310

    0.0310

    14.1100

    52.3590

    19

    0.0000

    0.0310

    0.0320

    0.0460

    0.0320

    14.1090

    51.8750

    20

    0.0000

    0.0310

    0.0320

    0.0460

    0.0320

    14.0780

    52.4840

    21

    0.0150

    0.0780

    0.0470

    0.0470

    0.0310

    16.3750

    59.5150

    22

    0.0000

    0.0310

    0.0310

    0.0470

    0.0320

    16.8900

    60.3440

    23

    0.0000

    0.0310

    0.0310

    0.0310

    0.0310

    16.3440

    60.0930

    24

    0.0000

    0.0310

    0.0310

    0.0470

    0.0310

    16.3440

    60.5780

    25

    0.0000

    0.0320

    0.0470

    0.0470

    0.0470

    16.3590

    59.7810

    26

    0.0160

    0.0470

    0.0310

    0.0470

    0.0310

    16.1250

    61.0620

    27

    0.0000

    0.0310

    0.0470

    0.0470

    0.0310

    16.7810

    59.6100

    28

    0.0150

    0.0320

    0.0320

    0.0470

    0.0310

    16.9220

    56.8130

    29

    0.0000

    0.0310

    0.0310

    0.0310

    0.0310

    15.0790

    57.8120

    30

    0.0000

    0.0310

    0.0320

    0.0460

    0.0320

    14.7810

    58.8280

    31

    0.0000

    0.0310

    0.0310

    0.0470

    0.0310

    15.8590

    59.1400

    32

    0.0000

    0.0470

    0.0320

    0.0310

    0.0310

    16.0940

    59.1560

    33

    0.0000

    0.0470

    0.0310

    0.0310

    0.0310

    15.9850

    59.1400

    34

    0.0000

    0.0310

    0.0310

    0.0470

    0.0320

    16.0150

    59.2500

    35

    0.0000

    0.0310

    0.0470

    0.0470

    0.0310

    16.7660

    57.9840

    36

    0.0000

    0.0310

    0.0320

    0.0470

    0.0310

    15.3750

    59.0470

    37

    0.0000

    0.0320

    0.0460

    0.0470

    0.0320

    16.0310

    58.9060

    38

    0.0000

    0.0310

    0.0310

    0.0470

    0.0310

    15.9530

    57.2650

    39

    0.0160

    0.0310

    0.0470

    0.0470

    0.0310

    15.9530

    57.5160

    40

    0.0150

    0.0310

    0.0320

    0.0470

    0.0310

    14.7030

    56.6710

    平均值

    0.0031

    0.0360

    0.0372

    0.0437

    0.0320

    15.9946

    58.7480

    最小值

    0.0000

    0.0160

    0.0310

    0.0310

    0.0310

    14.0780

    51.8750

    最大值

    0.0160

    0.0930

    0.0780

    0.0620

    0.0470

    17.3910

    62.8600

  • 相关阅读:
    渗透利器-kali工具 (第六章-1) 密码破解
    渗透利器-kali工具 (第五章-6) Metasploit后门生成模块
    渗透利器-kali工具 (第五章-5) Metasploit漏洞利用模块二
    渗透利器-kali工具 (第五章-4) Metasploit漏洞利用模块一
    渗透利器-kali工具 (第五章-3) Metasploit密码爆破模块
    渗透利器-kali工具 (第五章-2) Metasploit扫描漏洞模块
    渗透利器-kali工具 (第五章-1) Metasploit框架介绍与基本命令
    关于计算机网络的性能指标你需要知道这些
    写给大忙人看的计算机网络参考模型
    PHP基础编程之鬼斧神工的正则表达式-正则表达式基本语法+简单实例
  • 原文地址:https://www.cnblogs.com/allen8807/p/1879613.html
Copyright © 2020-2023  润新知