本次是算法課實驗,本人在此將每個算法都實現了一下,其中對桶排序算法還有較大改進空間,改用鏈表結構會快很多。
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++;
}
}