常见排序算法的实现与性能比较

本次是算法课实验,本人在此将每个算法都实现了一下,其中对桶排序算法还有较大改进空间,改用链表结构会快很多。

1.合并算法:将两个或两个以上的有序表组合成一个新的有序表,假定排序表含有n个元素,则可以看做n个有序子表,每个子表长度为1,然后两两归并,得到n/2个长度为2或者1的有序表;再进行两两归并,如此重复,直到合并成一个长度为n的有序表为止。

  合并算法是分治法的应用,其操作可以表示如下:

分解:将n个元素分成含有n/2个元素的子序列。

解决:用合并排序对两个子序列递归排序。

合并:合并两个已拍好序的子序列可得到排序结果。

性能分析:平均时间复杂度为,空间复杂度为O(n)

合并算法实现:

void mergeSort(int *arr,int first,int last,int *temp)     //归并算法

{

    if(first<last)

    {

        int mid=(first+last)/2;

        mergeSort(arr,first,mid,temp);

        mergeSort(arr,mid+1,last,temp);

        merge(arr,first,mid,last,temp);

    }

}

void merge(int *arr,int first,int mid,int last,int *temp)

{

    int i,j,k;

    for( k=first;k<=last;k++)

        temp[k]=arr[k];

    for(i=first,j=mid+1,k=i;i<=mid&&j<=last;k++)     //将剩余的部分接到arr

    {

        if(temp[i]<temp[j])

            arr[k]=temp[i++];

        else

            arr[k]=temp[j++];

    }  

    while(i<=mid)

        arr[k++]=temp[i++];

    while(j<=last)

        arr[k++]=temp[j++];

}

2.插入算法:每次讲一个待排序的记录,按照关键字大小插入到前面已经安排好的子序列中合适的位置,直到记录完成插入位置。

性能分析:平均时间复杂度为,空间复杂度为O(1)

插入算法实现:

void insertSort(int *arr,int length)            //插入排序

{

    for(int j=1;j!=length;j++)

    {

        int key = arr[j];

        int i=j-1;

        while((i>=0)&&arr[i]>key)

        {

            arr[i+1]=arr[i];

            i=i-1;

        }

        arr[i+1]=key;

    }

}

3.希尔排序:希尔排序又称为缩小增量排序,先将待排序序列分割成若干个子序列(拥有相同步长的),分别进行插入排序,然后缩小步长进行排序,直至步长为1在对全体进行插入排序。

性能分析:平均时间复杂度为,空间复杂度为

希尔排序实现:

//希尔排序算法的实现

void shellSort(int *arr,int length)

{

int d = length/2;   //设置希尔排序的增量

int i ;

int j;

int temp;

while(d>=1)

{

for(i=d;i<length;i++)

{

temp=arr[i];

j=i-d;

while(j>=0 && arr[j]>temp)

{

arr[j+d]=arr[j];

j=j-d;

}

arr[j+d] = temp;

}

d= d/2;    //缩小增量

}

}

4.快速排序:不断寻找一个序列的中点,然后对中点左右的序列递归的进行排序,直至全部序列排序完成,使用了分治的思想。

性能分析:平均时间复杂度为,空间复杂度为

快速排序实现:

void quickSort(int *arr,int p,int r)   //快速排序

{

if (p<r)

{

int q=partition(arr,p,r);

quickSort(arr,p,q-1);

quickSort(arr,q+1,r);

}

}

int partition(int *arr,int p,int r)

{

int x = arr[r];

int temp;

int i = p-1;

for(int j=p;j!=r;j++)

{

if (arr[j]<x)

{

i=i+1;

temp=arr[i];

arr[i]=arr[j];

arr[j]=temp;

}

}

temp=arr[r];

arr[r]=arr[i+1];

arr[i+1]=temp;

return i+1;

}

5.冒泡排序:将序列划分为无序和有序区,不断通过交换较大元素至无序区尾完成排序。

性能分析:平均时间复杂度为,空间复杂度为

冒泡排序实现:

void bullSort(int *arr,int length)     // 冒泡排序

{

int i,j;

int tmp;

for(i=0;i<length;i++)

{

for(j=0;j<length-i-1;j++)

{

if(arr[j]>arr[j+1])

{

tmp=arr[j];

arr[j]=arr[j+1];

arr[j+1]=tmp;

}

}

}

}

6.桶排序:假设有一组长度为N的待排关键字序列K[1....n]。首先将这个序列划分成M个的子区间(。然后基于某种映射函数 ,将待排序列的关键字k映射到第i个桶中(即桶数组B的下标 i) ,那么该关键字k就作为B[i]中的元素(每个桶B[i]都是一组大小为N/M的序列)。接着对每个桶B[i]中的所有元素进行比较排序(在这里我使用了插入排序)。然后依次枚举输出B[0]....B[M]中的全部内容即是一个有序序列。

我们需要尽量做到下面两点:

(1) 映射函数f(k)能够将N个数据平均的分配到M个桶中,这样每个桶就有[N/M]个数据量。

(2) 尽量的增大桶的数量。极限情况下每个桶只能得到一个数据,这样就完全避开了桶内数据的“比较”排序操作。

    在本次实验中,我采用了每个桶大小为50,设计了10000个桶,经过多次实验,每个桶的数据都不会超过50个。

性能分析:当设计合理的桶时,平均时间复杂度为,空间复杂度为

桶排序实现:

void bucketSort(int *arr,int length)

{

    int **temp=new int *[10000*sizeof(int *)];

    int count[10000]={0};

    int i,j,flag,k=0;

    for(i=0;i<10000;i++)

    {

        temp[i]=new int[50*sizeof(int)];

    }

    for(i=0;i<10000;i++)

        for(j=0;j<50;j++)

                temp[i][j]=0;

    for(i=0;i<length;i++)

    {

        flag=arr[i]/10;

        temp[flag][count[flag]]=arr[i];

        count[flag]++;

    }

    for(i=0;i<10000;i++)

    {

        for(j=1;j<count[i];j++)

        {

            int key =temp[i][j];

            int t = j-1;

            while((t>=0)&&temp[i][t]>key)

            {

                temp[i][t+1]=temp[i][t];

                t=t-1;

            }

            temp[i][t+1]=key;

        }

    }  

    for(i=0;i<10000;i++)

        for(j=0;j<count[i];j++)

        {

            arr[k]=temp[i][j];

            k++;

        }

}

在这我贴出最后的合成版代码

#include<iostream>
#include<math.h>
#include<iomanip>
#include<time.h>
#include<stdlib.h>
using namespace std;

void initialArr(int *arr,int length);
void disPlay(int *arr,int length);
void copyArr(int *arr,int *temp,int length);             //为了使各种算法对相同的数据进行排序,在排序之前要进行备份

void mergeSort(int *arr,int first,int last,int *temp);         //归并算法
void merge(int *arr,int first,int mid,int last,int *temp);

void insertSort(int *arr,int length);            //插入排序

void bullSort(int *arr,int length);       //冒泡排序

void shellSort(int *arr,int length);      //希尔排序

void quickSort(int *arr,int p,int r);    //快速排序
int partition(int *arr,int p,int r);

void bucketSort(int *arr,int length);     // 桶排序

int main()
{
	clock_t start,finish;
	double ptime;
    int arr[10];
    initialArr(arr,10);
    cout<<"当N=10时,原数组为:"<<endl;
    disPlay(arr,10);
	
    cout<<"经过归并排序以后,数组为:"<<endl;
	int temp[10];
    mergeSort(arr,0,9,temp);
    disPlay(arr,10);
	
    cout<<"经过插入排序以后,数组为:"<<endl;
	insertSort(arr,10);
	disPlay(arr,10);

    cout<<"经过希尔排序以后,数组为:"<<endl;
	shellSort(arr,10);
	disPlay(arr,10);

    cout<<"经过快排排序以后,数组为:"<<endl;
	quickSort(arr,0,9);
	disPlay(arr,10);

    cout<<"经过冒泡排序以后,数组为:"<<endl;
	bullSort(arr,10);
	disPlay(arr,10);

    cout<<"经过桶排排序以后,数组为:"<<endl;
	bucketSort(arr,10);
    disPlay(arr,10);

	system("pause");

//当N=1000时 各种算法运行的时间	
	int *arr1000=new int[1000];
	int *demo1000=new int[1000];
	initialArr(arr1000,1000);
	cout<<"当N=1000时,各种排序算法所需时间如下所示:"<<endl;            
	
//归并算法开始
	copyArr(arr1000,demo1000,1000);
	int temp1000[1000];
	start=clock();
    mergeSort(demo1000,0,999,temp1000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过归并排序,所需时间为:"<<ptime<<"秒"<<endl;


//插入排序算法开始
	copyArr(arr1000,demo1000,1000);
	start=clock();
    insertSort(demo1000,1000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过插入排序,所需时间为:"<<ptime<<"秒"<<endl;

	
//希尔排序算法开始
	copyArr(arr1000,demo1000,1000);
	start=clock();
    shellSort(demo1000,1000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过希尔排序,所需时间为:"<<ptime<<"秒"<<endl;


//快速排序算法开始
	copyArr(arr1000,demo1000,1000);	
	start=clock();
    quickSort(demo1000,0,999);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过快速排序,所需时间为:"<<ptime<<"秒"<<endl;


//冒泡排序算法开始
	copyArr(arr1000,demo1000,1000);
	start=clock();
    bullSort(demo1000,1000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过冒泡排序,所需时间为:"<<ptime<<"秒"<<endl;


//桶排序算法开始
	copyArr(arr1000,demo1000,1000);
	start=clock();
    bucketSort(demo1000,1000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过桶排序,所需时间为:"<<ptime<<"秒"<<endl;

//	delete []arr1000;
//	arr1000=NULL;
//	delete []demo1000;
//	demo1000=NULL;
	system("pause");

	
//当N=10000时 各种算法运行的时间	
	int *arr10000=new int[10000];
	int *demo10000=new int[10000];
	initialArr(arr10000,10000);
	cout<<"当N=10000时,各种排序算法所需时间如下所示:"<<endl;            
	
//归并算法开始
	copyArr(arr10000,demo10000,10000);
	int temp10000[10000];
	start=clock();
    mergeSort(demo1000,0,9999,temp10000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过归并排序,所需时间为:"<<ptime<<"秒"<<endl;

	
//插入排序算法开始
	copyArr(arr10000,demo10000,10000);	
	start=clock();
    insertSort(demo10000,10000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过插入排序,所需时间为:"<<ptime<<"秒"<<endl;
	
		
//希尔排序算法开始
	copyArr(arr10000,demo10000,10000);	
	start=clock();
    shellSort(demo10000,10000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过希尔排序,所需时间为:"<<ptime<<"秒"<<endl;
	
	
//快速排序算法开始
	copyArr(arr10000,demo10000,10000);	
	start=clock();
    quickSort(demo10000,0,9999);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过快速排序,所需时间为:"<<ptime<<"秒"<<endl;

	
//冒泡排序算法开始
	copyArr(arr10000,demo10000,10000);	
	start=clock();
    bullSort(demo10000,10000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过冒泡排序,所需时间为:"<<ptime<<"秒"<<endl;

	
//桶排序算法开始
	copyArr(arr10000,demo10000,10000);	
	start=clock();
    bucketSort(demo10000,10000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过桶排序,所需时间为:"<<ptime<<"秒"<<endl;

//	delete []arr10000;
//	arr10000=NULL;
//	delete []demo10000;
//	demo10000=NULL;
	
	system("pause");


//当N=100000时 各种算法运行的时间	
	int *arr100000=new int[100000];
	int *demo100000=new int[100000];
	initialArr(arr100000,100000);
	cout<<"当N=100000时,各种排序算法所需时间如下所示:"<<endl;            
	
//归并算法开始
	copyArr(arr100000,demo100000,100000);
	int temp100000[100000];
	start=clock();
    mergeSort(demo10000,0,99999,temp100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过归并排序,所需时间为:"<<ptime<<"秒"<<endl;

	
//插入排序算法开始
	copyArr(arr100000,demo100000,100000);
	start=clock();
    insertSort(demo100000,100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过插入排序,所需时间为:"<<ptime<<"秒"<<endl;
		
	
//希尔排序算法开始
	copyArr(arr100000,demo100000,10000);	
	start=clock();
    shellSort(demo100000,100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过希尔排序,所需时间为:"<<ptime<<"秒"<<endl;
	
	
//快速排序算法开始
	copyArr(arr100000,demo100000,100000);	
	start=clock();
    quickSort(demo100000,0,99999);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过快速排序,所需时间为:"<<ptime<<"秒"<<endl;

	
//冒泡排序算法开始
	copyArr(arr100000,demo100000,100000);
	start=clock();
    bullSort(demo100000,100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过冒泡排序,所需时间为:"<<ptime<<"秒"<<endl;

	
//桶排序算法开始
	copyArr(arr100000,demo100000,100000);
	start=clock();
    bucketSort(demo100000,100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"经过桶排序,所需时间为:"<<ptime<<"秒"<<endl;

//	delete []arr100000;
//	arr100000=NULL;
//	delete []demo100000;
//	demo100000=NULL;
	system("pause");


//当N=100000时 各种算法运行5次的平均时间	
	int *arr1=new int[100000];
	int *arr2=new int[100000];
	int *arr3=new int[100000];
	int *arr4=new int[100000];
	int *arr5=new int[100000];

	int *temp1=new int[100000];
	int *temp2=new int[100000];
	int *temp3=new int[100000];
	int *temp4=new int[100000];
	int *temp5=new int[100000];

	initialArr(arr1,100000);
	initialArr(arr2,100000);
	initialArr(arr3,100000);
	initialArr(arr4,100000);
	initialArr(arr5,100000);


	cout<<"当N=100000时,当N=100000时 各种算法运行5次的平均时间如下所示:"<<endl;            
	
	//归并算法开始
	copyArr(arr1,temp1,100000);
	copyArr(arr2,temp2,100000);
	copyArr(arr3,temp3,100000);
	copyArr(arr4,temp4,100000);
	copyArr(arr5,temp5,100000);
	//int temp100000[100000];
	start=clock();
    mergeSort(temp1,0,99999,temp100000);
	mergeSort(temp2,0,99999,temp100000);
	mergeSort(temp3,0,99999,temp100000);
	mergeSort(temp4,0,99999,temp100000);
	mergeSort(temp5,0,99999,temp100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC/5;
	cout<<"经过归并排序运行5次,平均所需时间为:"<<ptime<<"秒"<<endl;
	
	
	//插入排序算法开始
	copyArr(arr1,temp1,100000);
	copyArr(arr2,temp2,100000);
	copyArr(arr3,temp3,100000);
	copyArr(arr4,temp4,100000);
	copyArr(arr5,temp5,100000);
	start=clock();
    insertSort(temp1,100000);
	insertSort(temp2,100000);
	insertSort(temp3,100000);
	insertSort(temp4,100000);
	insertSort(temp5,100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC/5;
	cout<<"经过插入排序运行5次,平均所需时间为:"<<ptime<<"秒"<<endl;
	
	
	//希尔排序算法开始
	copyArr(arr1,temp1,100000);
	copyArr(arr2,temp2,100000);
	copyArr(arr3,temp3,100000);
	copyArr(arr4,temp4,100000);
	copyArr(arr5,temp5,100000);	
	start=clock();
    shellSort(temp1,100000);
	shellSort(temp2,100000);
	shellSort(temp3,100000);
	shellSort(temp4,100000);
	shellSort(temp5,100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC/5;
	cout<<"经过希尔排序运行5次,平均所需时间为:"<<ptime<<"秒"<<endl;
	
	
	//快速排序算法开始
	copyArr(arr1,temp1,100000);
	copyArr(arr2,temp2,100000);
	copyArr(arr3,temp3,100000);
	copyArr(arr4,temp4,100000);
	copyArr(arr5,temp5,100000);		
	start=clock();
    quickSort(temp1,0,99999);
	quickSort(temp2,0,99999);
	quickSort(temp3,0,99999);
	quickSort(temp4,0,99999);
	quickSort(temp5,0,99999);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC/5;
	cout<<"经过快速排序运行5次,平均所需时间为:"<<ptime<<"秒"<<endl;
	
	
	//冒泡排序算法开始
	copyArr(arr1,temp1,100000);
	copyArr(arr2,temp2,100000);
	copyArr(arr3,temp3,100000);
	copyArr(arr4,temp4,100000);
	copyArr(arr5,temp5,100000);	
	start=clock();
    bullSort(temp1,100000);
	bullSort(temp2,100000);
	bullSort(temp3,100000);
	bullSort(temp4,100000);
	bullSort(temp5,100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC/5;
	cout<<"经过冒泡排序运行5次,平均所需时间为:"<<ptime<<"秒"<<endl;
	
	
	//桶排序算法开始
	copyArr(arr1,temp1,100000);
	copyArr(arr2,temp2,100000);
	copyArr(arr3,temp3,100000);
	copyArr(arr4,temp4,100000);
	copyArr(arr5,temp5,100000);	
	start=clock();
    bucketSort(temp1,100000);
	bucketSort(temp2,100000);
	bucketSort(temp3,100000);
	bucketSort(temp4,100000);
	bucketSort(temp5,100000);
	finish=clock();
	ptime=(double)(finish-start)/CLOCKS_PER_SEC/5;
	cout<<"经过桶排序运行5次,平均所需时间为:"<<ptime<<"秒"<<endl;




    return 0;
}


void initialArr(int *arr,int length)
{
    srand((unsigned)time(NULL));
    for(int i=0;i<length;i++)
        arr[i]=1+100000.0*(rand()/(RAND_MAX+1.0));
}

void disPlay(int *arr,int length)
{
    for(int i=0;i<length;i++)    
    {   
        cout<<setw(10)<<arr[i];
        if((i+1)%10==0||i==length-1)
            cout<<endl;
    }   
}

void copyArr(int *arr,int *temp,int length)            //为了使各种算法对相同的数据进行排序,在排序之前要进行备份
{
	for (int i=0;i!=length;i++)
	{
		temp[i]=arr[i];
	}
}

void mergeSort(int *arr,int first,int last,int *temp)     //归并算法
{
    if(first<last)
    {
        int mid=(first+last)/2;
        mergeSort(arr,first,mid,temp);
        mergeSort(arr,mid+1,last,temp);
        merge(arr,first,mid,last,temp);
    }
}
void merge(int *arr,int first,int mid,int last,int *temp)
{
    int i,j,k;
    for( k=first;k<=last;k++)
        temp[k]=arr[k];
    for(i=first,j=mid+1,k=i;i<=mid&&j<=last;k++)     //将剩余的部分接到arr
    {
        if(temp[i]<temp[j])
            arr[k]=temp[i++];
        else
            arr[k]=temp[j++];
    }  
    while(i<=mid)
        arr[k++]=temp[i++];
    while(j<=last)
        arr[k++]=temp[j++];
}


void insertSort(int *arr,int length)            //插入排序
{
    for(int j=1;j!=length;j++)
    {
        int key = arr[j];
        int i=j-1;
        while((i>=0)&&arr[i]>key)
        {
            arr[i+1]=arr[i];
            i=i-1;
        }
        arr[i+1]=key;
    }
}


void bullSort(int *arr,int length)     // 冒泡排序
{
	int i,j;
	int tmp;
	for(i=0;i<length;i++)
	{
	
		for(j=0;j<length-i-1;j++)
		{	
			if(arr[j]>arr[j+1])
			{
				tmp=arr[j];
				arr[j]=arr[j+1];
				arr[j+1]=tmp;	
			}
		}
	}
}


void quickSort(int *arr,int p,int r)   //快速排序
{
	if (p<r)
	{
		int q=partition(arr,p,r);
		quickSort(arr,p,q-1);
		quickSort(arr,q+1,r);
	}
}

int partition(int *arr,int p,int r)
{
	int x = arr[r];
	int temp;
	int i = p-1;
	for(int j=p;j!=r;j++)
	{
		if (arr[j]<x)
		{
			i=i+1;
			temp=arr[i];
			arr[i]=arr[j];
			arr[j]=temp;
		}
	}
	temp=arr[r];
	arr[r]=arr[i+1];
	arr[i+1]=temp;
	return i+1;
}


//希尔排序算法的实现
void shellSort(int *arr,int length)
{	
	int d = length/2;   //设置希尔排序的增量	
	int i ;	
	int j;	
	int temp;	
	while(d>=1)		
	{		
		for(i=d;i<length;i++)			
		{			
			temp=arr[i];
			j=i-d;			
			while(j>=0 && arr[j]>temp)			
			{			
				arr[j+d]=arr[j];
				j=j-d;			
			}			
			arr[j+d] = temp;			
		}				
		d= d/2;    //缩小增量		
	}	
}



void bucketSort(int *arr,int length)
{
    int **temp=new int *[10000*sizeof(int *)];
    int count[10000]={0};
    int i,j,flag,k=0;
    for(i=0;i<10000;i++)
    {
        temp[i]=new int[50*sizeof(int)];
    }
    for(i=0;i<10000;i++)
        for(j=0;j<50;j++)
                temp[i][j]=0;
    for(i=0;i<length;i++)
    {
        flag=arr[i]/10;
        temp[flag][count[flag]]=arr[i];
        count[flag]++;
    }

    for(i=0;i<10000;i++)
    {
        for(j=1;j<count[i];j++)
        {
            int key =temp[i][j];
            int t = j-1;
            while((t>=0)&&temp[i][t]>key)
            {
                temp[i][t+1]=temp[i][t];
                t=t-1;
            }
            temp[i][t+1]=key;
        }
    }  
    for(i=0;i<10000;i++)
        for(j=0;j<count[i];j++)
        {
            arr[k]=temp[i][j];
            k++;
        }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值