《排序问题求解》实验报告一、算法得基本思想1、直接插入排序算法思想直接插入排序得基本思想就是将一个记录插入到已排好序得序列中,从而得到一个新得,记录数增 1 得有序序列。
直接插入排序算法得伪代码称为InsertionSort,它得参数就是一个数组A[1、、n],包含了n个待排序得数。
用伪代码表示直接插入排序算法如下:InsertionSort (A)for i←2 tondo key←A[i]//key 表示待插入数//Insert A[i] into thesortedsequence A[1、、i-1]j←i-1while j>0 andA[j]>keydo A[j+1]←A[j]j←j-1A[j+1]←key2、快速排序算法思想快速排序算法得基本思想就是,通过一趟排序将待排序序列分割成独立得两部分,其中一部分记录得关键字均比另一部分记录得关键字小,则可对这两部分记录继续进行排序,以达到整个序列有序。
假设待排序序列为数组A[1、、n],首先选取第一个数A[0],作为枢轴(pivot),然后按照下述原则重新排列其余数:将所有比A[0]大得数都排在它得位置之前,将所有比A[0]小得数都排在它得位置之后,由此以A[0]最后所在得位置i 作为分界线,将数组A[1、、n]分成两个子数组A[1、、i-1]与A[i+1、、n]。
这个过程称作一趟快速排序。
通过递归调用快速排序,对子数组A[1、、i-1]与A[i+1、、n]排序。
一趟快速排序算法得伪代码称为Partition,它得参数就是一个数组A[1、、n]与两个指针low、high,设枢轴为pivotkey,则首先从high所指位置起向前搜索,找到第一个小于pivotkey得数,并将其移到低端,然后从low 所指位置起向后搜索,找到第一个大于pivotkey 得数,并将其移到高端,重复这两步直至low=high。
最后,将枢轴移到正确得位置上。
用伪代码表示一趟快速排序算法如下:Partition ( A,low,high)A[0]←A[low]//用数组得第一个记录做枢轴记录privotkey←A[low]//枢轴记录关键字while low<high //从表得两端交替地向中间扫描while low<high &&A[high]>=privotkey do high←high-1A[low]←A[high] //将比枢轴记录小得记录移到低端while low<high &&A[low]<=pivotkey)dolow←low+1A[high]←A[low] //将比枢轴记录大得记录移到高端A[low]←A[0] //枢轴记录到位return low //返回枢轴位置二、算法得理论分析1、直接插入排序算法理论分析从空间来瞧,直接插入排序只需要一个数得辅助空间;从时间来瞧,直接插入排序得基本操作为:比较两个关键字得大小与移动记录。
先分析一趟直接插入排序得情况。
伪代码InsertionSort中while循环得次数取决于待插入得数与前i-1 个数之间得关系。
若A[i]<A[0],则在while 循环中,待插入数需与有序数组A[1、、i-1]中i-1个数进行比较,并将A[i-1]中i-1个数后移。
则在整个排序过程(进行n-1 趟插入排序)中,当待排序数组中数按非递减有序排列时,则需进行数间比较次数达最小值n-1,数不需要移动;反之,当待排序数组中数按非递增有序排列时,总得比较次数达最大值(n+2)(n-1)/2,数移动得次数也达到最大值(n+4)(n-1)/2。
若待排序数组就是随机得,即待排序数组中得数可能出现得各种排序得概率相同,则我们可取上述最小值与最大值得平均值,作为直接插入排序时所需进行数间得比较次数与数得移动次数,约为n^2/4。
因此直接插入排序算法,在最佳情况下得时间复杂度就是O(n),在最坏情况下得时间复杂度为O(n^2)。
2、快速排序算法理论分析下面我们来分析快速排序得平均时间性能。
假设T(n)为对n 个记录A[1、、n]进行快速排序所需时间,则由算法QuickSort 可见:其中,Tpass(n)为对n 个记录进行一趟快速排序Partition(A,1,n)所需得时间,从一趟快速排序算法可见,其与记录数n成正比,可以用cn表示(c 为某个常数);T(k-1)与T(n-k)分别为对A[1、、k-1]与A[k+1、、n]中记录进行快速排序QuickSort(A,1,k-1)与QuickSort(A,k+1,n)所需时间。
假设待排序列中记录就是随机排列得,则在一趟排序之后,k 取 1 至n 之间任何一值得概率相同,快速排序所需时间得平均值则为Tavg(n)=knInn,其中n 为待排序序列中记录得个数,k为某个常数。
通常,快速排序被认为就是,在所有同数量级(O(nlogn))得排序方法中,其平均性能最好。
但就是,若初始记录序列按关键字有序或基本有序时,快速排序将蜕化为起泡排序,其时间复杂度为O(n^2)。
三、试验分析1、试验环境WIN 32系统,VC6、02、程序得执行1)由函数datagenetare()生成20000 个在区间[1,100000]上得随机整数,并将随机整数保存到数组num[],接着调用函数WriteFile()将这些数输出到外部文件data、txt 中。
2)调用函数ReadFile()从data、txt中读取数据,并将其保存到数组num1[]中。
接着对数组num1 进行直接插入排序,并计算与记录其运行时间。
最后,调用函数WriteFile()将直接插入排序得结果写入resultsIS、txt,并记录运行时间为TimeIS。
3)调用函数ReadFile()从data、txt 中读取数据,并将其保存到数组num2[]中。
接着对数组num2进行快速排序,并计算与记录其运行时间。
最后,调用函数WriteFile()将快速排序得结果写入resultsQS、txt,并记录运行时间为TimeQS。
3、试验数据当N=20000时:当N=30000时:当N=40000时:当N=50000时:当N=60000时:当N=70000时:当N=80000时:2 0插入排序0、3250、719 1、397 2、1993、054、5715、46快速排序 0、003 0、005 0、008 0、01 0、0120、011 0、013四、试验心得通过本次试验首先对在C++下得文件操作有了一定得深入认识,对于快速排序与插入排序得时间有了相当清晰且一目了然得认识,并且从原理上明白了快速排序得快得原因,对各种排序算法得优劣性有了全局得认识!五、实验代码#include <iostream>#include<ctime>#include <cstdlib>#include<fstream>#include <string>using namespacestd;constint NumS = 80000;voiddatagenetare(int num[],int n); //产生随机数,保存到数组numvoid Write num[],char name[],int n);//输出数组num到data、txt文件void Read num[],char name[]);//读取名为name文件中得数据,保存到数组numvoid QuickSort(int arr[], intn);//将数组arr[]中数据快速排序voidInsertionSort(int arr[],intn);//将数组arr[]中数据直接插入排序int main(){ﻩint*num=(int *)malloc(sizeof(int)*NumS);int*num1=(int*)malloc(sizeof(int)*NumS);ﻩint *num2=(int*)malloc(sizeof(int)*NumS);ﻩclock_t start_time1,end_time1,start_time2,end_time2;ﻩdouble timeQS=0,timeIS=0;ﻩcout<<"Create "<<NumS<<"randomnumbers from 1 to 100000"<<en dl;ﻩdatagenetare(num,NumS); //产生随机数,保存到数组numWrite,"data、txt",NumS);//输出数组到data、txt文件ﻩcout、precision(6); //设置浮点数得显示精度cout、setf(ios_base::showpoint); //输出末尾得//直接插入排序得分析Read,"data、txt");//读取data、txt中得数据,保存到数组num1cout<<"\nInsertionSort Start、、、、\n";start_time1=clock(); //开始计时InsertionSort(num1,NumS); //直接插入排序数组num1中得数据end_time1=clock(); //结束计时timeIS=(double)(end_time1-start_time1)/CLOCKS_PER_SEC;cout<<"The Time-suptionin InsertionSortis "<<timeIS<<" seconds!\n\n"; //输出运行时间ﻩﻩWrite,"resultsIS、txt",NumS); //排序后得数据输出到resultQS、txt ﻩ//输出运行时间timeIS到resultsIS、txtofstream ocout;ﻩocout、open("resultsIS、txt",ios::app);ﻩif(ocout、good()) //打开resultsIS、txt{ﻩﻩocout<<"\nThe Time-suptionin InsertionSortis"<<timeIS<<" seconds\n";ﻩocout、close();ﻩ}else{ﻩﻩcout<<"\nCan not open resultsIS、txt!\n";ﻩexit(1);//异常退出ﻩ}//快速排序得分析Read,"data、txt");//读取data、txt中得数据,保存到数组num2[]ﻩcout<<"QuickSortStart、、、、、\n";ﻩstart_time2=clock(); //开始计时ﻩQuickSort(num2,NumS);//快速排序数组num中得数据end_time2=clock();//结束计时timeQS=(double)(end_time2-start_time2)/CLOCKS_PER_SEC;ﻩcout<<"The Time-suption in QuickSortis"<<timeQS<<" seconds:\n"; //输出运行时间Write,"resultsQS、txt",NumS); //排序后得数据输出到resultQS、txtﻩ//输出运行时间timeQS到resultsQS、txtﻩocout、open("resultsQS、txt",ios::app);if(ocout、good()) //打开resultsIS、txtﻩ{ﻩocout<<"\nThe Time-suption in QuickSort is"<<timeQS<<"seco nds\n";ocout、close();ﻩ}else{cout<<"\nCannot open resultsQS、txt!\n";exit(1); //异常退出ﻩ}return0;}void datagenetare(int*num,int n){ﻩint i;srand((unsigned)time(0)); //srand()种子发生器函数,还有rand()随机数生成器函数for(i=0;i<n;i++) //产生个到之间得随机数ﻩnum[i]=rand()%9999+1;printf("\n");}//将数组中得数据输出到文件void Write*num,char name[],intn){ﻩofstream ocout;ocout、open(name,ios::trunc);int i=0;if(ocout、fail())exit(1);//打开文件失败,退出for(;i<n;i++){ﻩocout<<num[i]<<" ";ﻩif((i+1)%40==0||i==n-1) //每输出40个数,换一行ﻩﻩocout<<"\n";}ocout、close();}//将文件中得数据输入到数组voidRead *num,charname[]){ﻩstring strLine;inti=0;char achLine[300];ﻩconst char* pchTok;ﻩifstreamicin;icin、open(name,ios::in);//打开名为name得文件while(icin、good())ﻩ{ﻩﻩint i = 0;while(getline(icin,strLine))ﻩ{ﻩﻩstrLine、copy(achLine,strLine、size(),0);ﻩﻩachLine[strLine、size()]='\0';//每行中得元素以空格为标识断开转换为int类型后存入数组ﻩﻩpchTok =strtok(achLine, " ");ﻩﻩwhile((pchTok != NULL))ﻩ{ﻩﻩnum[i]= atoi(pchTok);ﻩﻩﻩﻩi++;ﻩﻩﻩpchTok =strtok(NULL,"");}}}icin、close();}//快速排序得实现,从左向右递增排序void QuickSort(int *arr,int n){ﻩint L =0;int R =n-1;ﻩint t = arr[L]; //区间得第一个数作为基准ﻩif(n<=1) //数组中存在个或个数据时,函数返回ﻩreturn;ﻩ//将数据分成两个区间while(L<R){ //区间内至少存在一个元素得情况while(L<R&&t<=arr[R]) R--;//从右向左搜索,直到第一个小于t得数arr[R] ﻩarr[L] = arr[R];ﻩwhile(L<R&&arr[L]<=t) L++;//从左向右搜索,找到第一个大于t得数arr[L] ﻩarr[R] =arr[L];ﻩ}ﻩarr[L] = t;QuickSort(arr, L); //对左区间递归排序QuickSort(arr+L+1,n-L-1);//对右区间递归排序}//直接插入排序得实现,从左向右递增排序voidInsertionSort(int *arr,intn){ﻩint i=0,temp=0,j=0;ﻩif(n<=1)ﻩreturn;ﻩfor(i=1;i<n;++i){ﻩﻩtemp=arr[i]; //temp记录要插入得数据arr[i]j=i; //要插入得数据得位置ﻩﻩfor(;j>0&&arr[j-1]>temp;--j) //将a[i]插入到已排序得arr[0]~arr[i-1]中ﻩ{arr[j]=arr[j-1]; //比temp大得数据依次后移ﻩ}ﻩﻩarr[j]=temp; //找到第一个不大于于temp得数据,在j处插入arr[i]ﻩ}}。