当前位置:文档之家› 数据结构课程设计报告---几种排序算法的演示(附源代码)

数据结构课程设计报告---几种排序算法的演示(附源代码)

数据结构课程设计报告—几种排序算法的演示时间:2010-1-14一需求分析运行环境Microsoft Visual Studio 2005程序所实现的功能对直接插入排序、折半插入排序、冒泡排序、简单选择排序、快速排序、堆排序、归并排序算法的演示,并且输出每一趟的排序情况。

程序的输入(包含输入的数据格式和说明)<1>排序种类三输入<2>排序数的个数的输入<3>所需排序的所有数的输入程序的输出(程序输出的形式)<1>主菜单的输出<2>每一趟排序的输出,即排序过程的输出二设计说明算法设计思想<1>交换排序(冒泡排序、快速排序)交换排序的基本思想是:对排序表中的数据元素按关键字进行两两比较,如果发生逆序(即排列顺序与排序后的次序正好相反),则两者交换位置,直到所有数据元素都排好序为止。

<2>插入排序(直接插入排序、折半插入排序)插入排序的基本思想是:每一次设法把一个数据元素插入到已经排序的部分序列的合适位置,使得插入后的序列仍然是有序的。

开始时建立一个初始的有序序列,它只包含一个数据元素。

然后,从这个初始序列出发不断插入数据元素,直到最后一个数据元素插到有序序列后,整个排序工作就完成了。

<3>选择排序(简单选择排序、堆排序)选择排序的基本思想是:第一趟在有n个数据元素的排序表中选出关键字最小的数据元素,然后在剩下的n-1个数据元素中再选出关键字最小(整个数据表中次小)的数据元素,依次重复,每一趟(例如第i趟,i=1,…,n-1)总是在当前剩下的n-i+1个待排序数据元素中选出关键字最小的数据元素,作为有序数据元素序列的第i个数据元素。

等到第n-1趟选择结束,待排序数据元素仅剩下一个时就不用再选了,按选出的先后次序所得到的数据元素序列即为有序序列,排序即告完成。

<4>归并排序(两路归并排序)两路归并排序的基本思想是:假设初始排序表有n个数据元素,首先把它看成是长度为1的首尾相接的n个有序子表(以后称它们为归并项),先做两两归并,得n/2上取整个长度为2的归并项(如果n为奇数,则最后一个归并项的长度为1);再做两两归并,……,如此重复,最后得到一个长度为n的有序序列。

程序的主要流程图程序的主要模块(要求对主要流程图中出现的模块进行说明)程序的主要模块主要分为主菜单模块和排序算法演示模块。

<1>主菜单主要功能:程序运行时,可使运行者根据提醒输入相关操作,从而进入不同的排序方法或者退出。

<2>排序方法及输出根据运行者对排序的不同选择,进入排序过程a.直接插入排序:根据直接排序的算法,输出排序过程b.折半插入排序:根据折半插入的算法,输出排序过程c.冒泡排序:根据冒泡排序算法,输出排序过程d.简单选择排序:根据简单选择排序的算法,输出排序过程e.快速排序:根据快速排序的算法,输出排序过程f.堆排序:根据堆排序的算法,输出排序过程g.归并排序:根据归并排序的算法,输出排序过程程序的主要函数及其伪代码说明<1>模板类主要说明程序中用到的类的定义template<class type>class sortlist{ private:int currentsize;排序表中的数据元素,利用堆的调整算法形成初始堆。

b.输出堆顶元素。

c.对剩余元素重新调整形成堆。

d.重复执行第b 、c 步,直到所有数据元素被输出。

(1)建立最大堆的伪代码如下:template <class type>此循环,当i 与j 中有一个已经超出表长时,将另一个表中的剩余部分照抄到新表C[k]~C[m+n]中。

下面的归并算法中,两个待归并的有序表首尾相接存放在数组[]中,其中第一个表的下标范围从left 到mid ,另一个表的下标范围从mid+1到right 。

前一个表中有mid-left+1个数据元素,后一个表中有right –mid 个数据元素。

归并后得到的新有序表有right –mid 个数据元素。

归并后得到的新有序表存放在另一个辅助数组[]中,其下标范围从left 到right 。

伪代码如下:template <class type> voidsortlist<type>::merge(sortlist<type>&sourcetable,sortlist<type>&mergedtable,con st int left,const int mid,const int right) {int i=left,j=mid+1,k=left;快速排序(不稳定的排序方法) 1.时间复杂度最好情况(每次总是选到中间值作枢轴)T(n)=O(nlog2n) 最坏情况(每次总是选到最小或最大元素作枢轴)T(n)=O(n2)1111-=∑-=n n i 22)1(211n n n i n i ≈-=∑= 22)1)(4()2(211n n i n i ≈-+=+∑= 42n 42n )(21)(211n n i n n i -=-∑-=)(23)(321n n i n n i -=-∑=2.空间复杂度:需栈空间以实现递归最坏情况:S(n)=O(n)一般情况:S(n)=O(log2n)f. 堆排序(不稳定的排序方法)]1.间复杂性为O(nlog2n)。

2空间复杂性为O(1)。

g. 归并排序(稳定的排序方法)1时间复杂度为O(nlog2n)。

2空间复杂度为O(n)。

3)运行情况主菜单直接插入排序折半插入排序冒泡排序简单选择排序快速排序堆排序归并排序退出系统1)上机过程中出现的问题及其解决方案1 快速排序时出现多一次排序的情况解决方法:在进行循环体时,多运行了一次,将运行次序减1即可。

2 堆排序时也出现与上一条相同的情况解决方法:由于缺少一个判断语句导致输出只能是偶数倍趟数,因此加一条if(len<=currentsize-1)判断语句就可以使程序正常输出结果3 快速排序趟数开始为1 ,2 ,1, 2出现解决方法:再定义一个全局变量,不过当其用完时,没有将它重新置为0,这样最后输出的趟数就正确了。

4 运行程序时,若输入字符,则必须输入完全后,才判断其为不正确的选择解决方法:加一个if判断语句即可2)程序中可以改进的地方说明本程序不能判断字符数大于1的字符串,这方面需要改进可以在程序中加入性能分析,例如空间复杂度,时间复杂度等3)程序中可以扩充的功能及其设计实现假想扩充功能:可以加入希尔排序等未加入的排序方法,可以加入性能分析实现假想:加入其他排序方法后,输出为正确排序的过程,加入性能分析时,输出排序过程的同时,可以输出时间复杂度与空间复杂度6) 收获及体会在进行为期一个星期的课程设计中,最终完成了算法。

这期间,遇到的各种麻烦也都相继解决。

从这次实践中,我意识到自己还有很多不足之处。

首先先说一下基本的。

对于各种排序算法的过程还是不够熟悉,进行编程时还需要翻书查找,对于这一点,只能说对数据结构的学习还不够扎实,虽然说这门课程以后就没有了,但是我想这门课对以后的学习会有很大帮助,所以有空时还应该继续熟悉这门课程。

其次,就是对于错误的处理,不能得心应手,不能正确处理一些简单的错误。

对于逻辑上的错误,不能够立即找到出错点,往往需要向同学请教才能找出错误,并且改正。

我觉得这是自己独自思考能力不高的问题,遇事需要自己仔细想想,若还不能改正,再请教别人也不迟。

从总体上说,整个代码的实现还是存在不足的,例如本程序不能判断字符数大于1的字符串,没有相应排序的性能分析(如空间复杂度,时间复杂度),等等。

从这点看,说明自己的程序还是不够完善,不能做到十全十美,希望以后能有所修正。

总而言之,从这次的实践中我学到了很多东西,希望以后能够多加运应7) 源代码:#include""#include<iostream>using namespace std;const int maxsize=100;int num=0;//定义全局变量,为每一趟的输出做准备int x=0;template<class type>class sortlist{private:int currentsize;//数据表中数据元素的个数public:type *arr;//存储数据元素的向量(排序表)sortlist():currentsize(0){arr=new type[maxsize];}//构造函数sortlist(int n){arr=new type[maxsize];currentsize=n;}void insert(int i,type x){arr[i]=x;}~sortlist(){delete []arr;}//析构函数void swap(type &x,type &y)//数据元素x和y交换位置{type temp=x;x=y;y=temp;}void bubblesort();//冒泡排序void quicksort(int low,int high);//快速排序void insertionsort();//直接插入排序void binaryinsertsort();//折半插入排序void selectsort();//简单选择排序void heapsort();//堆排序void mergesort(sortlist<type> &table);//归并排序void filterdown(const int start);//建立最大堆void mergepass(sortlist<type>&sourcetable,sortlist<type>&mergedtable,const int len);//一趟归并void merge(sortlist<type>&sourcetable,sortlist<type>&mergedtable,const int left,const int mid,const int right);//两路归并算法};template <class type>//直接插入排序void sortlist<type>::insertionsort(){type temp;int j;for(int i=1;i<=currentsize-1;i++){temp=arr[i];j=i-1;while(j>=0&&temp<arr[j]){arr[j+1]=arr[j];j--;}arr[j+1]=temp;cout<<"第"<<++num<<"趟排序结果为:";for(int t=0;t<currentsize;t++) cout<<arr[t]<<" ";cout<<endl;}num=0;}template <class type>//折半插入排序void sortlist<type>::binaryinsertsort(){type temp;int left,right;for(int i=1;i<currentsize;i++){left=0;right=i-1;temp=arr[i];while(left<=right)//找插入位置{int mid=(left+right)/2;if(temp<arr[mid])right=mid-1;else left=mid+1;}for(int k=i-1;k>=left;k--)//向后移动arr[k+1]=arr[k];arr[left]=temp;cout<<"第"<<++num<<"趟排序结果为:";for(int t=0;t<currentsize;t++)cout<<arr[t]<<" ";cout<<endl;}num=0;}template <class type>//冒泡排序void sortlist<type>:: bubblesort(){int i=1;int finish=0;//0表示还没有排好序while(i<currentsize &&!finish){finish=1;//排序结束标志置为,假定已经排好序for(int j=0;j<currentsize-i;j++)if(arr[j]>arr[j+1])//逆序{swap(arr[j],arr[j+1]);//相邻元素交换位置finish=0;}//排序结束标志置为,表示本趟发生了交换,说明还没有排好序i++;cout<<"第"<<++num<<"趟排序结果为:";for(int t=0;t<currentsize;t++)cout<<arr[t]<<" ";cout<<endl;}num=0;}template <class type>void sortlist<type>::selectsort()//简单选择排序{int k;for(int i=0;i<currentsize-1;i++){k=i;for(int j=i+1;j<currentsize;j++)if(arr[j]<arr[k])k=j;//k 指示当前序列中最小者的位置if(k!=i)//最小关键字的数据元素位置不等于iswap(arr[i],arr[k]);cout<<"第"<<++num<<"趟排序结果为:";for(int t=0;t<currentsize;t++)cout<<arr[t]<<" ";cout<<endl;}num=0;}template <class type>//快速排序void sortlist<type>::quicksort(int low,int high)//在待排序区间[low,high]上,递归地进行快速排序{int i=low,j=high;type temp=arr[low];//取区间第一个位置为基准位置if(i<j){while(i<j){while(i<j&&temp<arr[j])j--;if(i<j){swap(arr[i],arr[j]);i++;}while(i<j&&temp>=arr[i])i++;if(i<j){swap(arr[i],arr[j]);j--;}}arr[i]=temp;//将基准元素就位cout<<"第"<<++x<<"趟排序结果为:";for(int t=0;t<currentsize;t++)cout<<arr[t]<<" ";cout<<endl;quicksort(low,i-1);//在左子区间递归进行快速排序quicksort(i+1,high);//在右子区间递归进行快速排序}}template <class type>//建立最大堆void sortlist<type>::filterdown(const int start){//向下调整使从start开始到currentsize-1为止的子表成为最大堆int i=start,j=2*i+1;//j为i的左孩子int tablesize=currentsize;type temp=arr[i];while(j<=currentsize-1){if(j<currentsize-1 && arr[j]<arr[j+1])j++;//在两个孩子中选关键字较大者if(temp>=arr[j])break;else{arr[i]=arr[j];i=j;j=2*j+1;}}arr[i]=temp;}template <class type>void sortlist<type>::heapsort(){int tablesize=currentsize;for(int i=(currentsize-2)/2;i>=0;i--)filterdown(i); //初始建堆for(int i=currentsize-1;i>=1;i--){swap(arr[0],arr[i]);//堆顶元素和最后一个元素交换currentsize--;filterdown(0);//重建最大堆cout<<"第"<<++num<<"趟排序结果为:";for(int t=0;t<tablesize;t++)cout<<arr[t]<<" ";cout<<endl;}num=0;currentsize=tablesize;}template <class type>voidsortlist<type>::merge(sortlist<type>&sourcetable,sortlist<type>&mergedtable,con st int left,const int mid,const int right){int i=left,j=mid+1,k=left;//指针初始化//i是前一段的当前元素位置,j是后一段的当前元素位置,k是辅助数组的当前位置while(i<=mid&&j<=right)if[i]<=[j]){[k]=[i];i++;k++;}else{[k]=[j];j++;k++;}if(i<=mid)for(int p=k,q=i;q<=mid;p++,q++)[p]=[q];//把前一段复制到mergedtableelsefor(int p=k,q=j;q<=right;p++,q++)[p]=[q];//把后一段复制到mergedtable}template <class type>voidsortlist<type>::mergepass(sortlist<type>&sourcetable,sortlist<type>&mergedtable ,const int len){int i=0;while(i+2*len<=currentsize-1)//表示至少有个子序列{merge(sourcetable,mergedtable,i,i+len-1,i+2*len-1);i+=2*len;}if(i+len<=currentsize-1)//若只有最后两个子序列merge(sourcetable,mergedtable,i,i+len-1,currentsize-1);else//若只有最后一个子序列for(int j=i;j<=currentsize-1;j++)[j]=[j];if(len<=currentsize-1){if(num<currentsize){cout<<"第"<<++num<<"趟排序结果为:";for(int t=0;t<currentsize;t++)cout<<[t]<<" ";cout<<endl;}}}template <class type>void sortlist<type>::mergesort(sortlist<type> &table ){//按数据元素关键字非递减的顺序对排序表table中数据元素进行递归排序sortlist<type> temptable;int len=1;while(len<currentsize){mergepass(table,temptable,len);len*=2;mergepass(temptable,table,len);len*=2;}num=0;}int main()//主函数{cout<<"***********************************************************************"<<endl; cout<<" 排序问题 "<<endl;cout<<"***********************************************************************" <<endl<<endl<<endl;int c=1;char ch,cc;int n1=0;while(c!=0){cout<<"\n======================================================================="<<endl;cout<<"======================可供选择的排序方法=============================="<<endl; cout<<" 1 直接插入排序 2 折半插入排序 "<<endl; cout<<" 3 冒泡排序 4 简单选择排序 "<<endl; cout<<" 5 快速排序 6 堆排序 "<<endl; cout<<" 7 归并排序 0 退出排序程序 "<<endl; cout<<"======================================================================="<<endl;cout<<"\n 请输入您需要的排序种类:";cin>>ch;if(ch=='0') {cout<<" 您已成功退出该系统!"<<endl;system("pause"); return 0;} int n,number;if(ch>='0'&&ch<='7'){cout<<"\n 输入您要进行排序的数的个数:";cin>>n;cout<<"\n 请输入"<<n<<"个数:";sortlist<int>table(n);for(int i=0;i<n;i++){cin>>number;(i,number);}switch(ch){case'1':cout<<"\n *******您选择的是直接插入排序*******\n"<<endl;();break;system("pause");break;case'2':cout<<"\n *******您选择的是折半插入排序*******\n"<<endl;();break;system("pause");break;case'3':cout<<"\n *******您选择的是冒泡排序*******\n"<<endl;();break;system("pause");break;case'4':cout<<"\n *******您选择的是简单选择排序*******\n"<<endl;();break;system("pause");break;case'5':cout<<"\n *******您选择的是快速排序*******\n"<<endl;(0,n-1);break;system("pause");break;case'6':cout<<"\n *******您选择的是堆排序*******\n"<<endl;();break;system("pause");break;case'7':cout<<"\n *******您选择的是归并排序*******\n"<<endl;(table);break;system("pause");break;}}}system("pause");return 0;}四参考文献:《数据结构——C++实现》。

相关主题