冒泡排序选择排序堆排序算法课程设计汇总.docx
- 文档编号:30750656
- 上传时间:2023-08-20
- 格式:DOCX
- 页数:28
- 大小:190.95KB
冒泡排序选择排序堆排序算法课程设计汇总.docx
《冒泡排序选择排序堆排序算法课程设计汇总.docx》由会员分享,可在线阅读,更多相关《冒泡排序选择排序堆排序算法课程设计汇总.docx(28页珍藏版)》请在冰豆网上搜索。
冒泡排序选择排序堆排序算法课程设计汇总
《算法设计与分析导论》
课程设计
题目:
排序
院系:
000000000000000000
专业:
00000000000000
学号姓名:
0000000000000000
指导老师:
0000
日期:
2017年6月20日
摘要
排序是计算机程序设计的一种重要操作,它的功能是将一组任意顺序的数据元素,根据一个或几个关键字按照一定的顺序重新排列成为有序的序列。
.如何进行排序,特别是高效地处理进行排序是计算机应用中的主要课题之一。
由于待排序的记录数量不同,使得排序过程中能涉及的存储器不同,可将排序方法分为两大类:
一类是内部排序,指的是待排序的记录存放在计算机随机存储器中进行的排序过程;另一类是外部排序,指的是待排序的记录数量很大,以致内存不能一次容纳全部记录,在排序过程中尚需要对外存进行访问的排序过程。
本次课程设计就是研究内部排序中的三个常用的排序方法:
直接插入排序、冒泡排序、堆排序。
分析排序的实质,排序的应用。
应用Java语言采用数组存储结构实现了三个排序算法,利用面向对象编程实现了本排序的综合系统。
关键词:
排序,数据处理,时间复杂度
引言
由于排序运算在计算机应用中所处的重要地位,熟悉内部排序法的排序过程和各种算法的时间复杂度分析结果及其分析方法,以便在实际应用中,根据实际问题要求,选用合适的排序方法。
本次课程设计目的是通过程序语言设计并实现三种排序算法,直接插入排序、冒泡排序、堆排序的综合系统。
通过对不同的数据计量进行实际排序对结构进行分析,找出它们之间的优势和劣势,并结合理论总结在实际运用排序算法过程中需要注意的问题。
1需求分析
1.1任务
输入N个乱序的数字,对这些数据分别采用直接插入排序、冒泡排序、堆排序进行排序,输出排序后的数据、数据的个数和排序所花费的时间。
分析在相同数据下,采用不同算法所耗时间的差别。
1.2功能模块的划分
1.2.1选择排序方法模块
通过点击界面的单选按钮来选择何种算法进行排序,包括的算法有:
直接插入排序、冒泡排序、堆排序。
1.2.2输入模块
在文本框上输入需要排序的数据,数据可以使整型,也可是浮点型。
数据之间用空格分开。
1.1.3输出模块
在输出文本框上输出排序后的数据、数据的个数N还有排序数据所耗的时间。
1.3排序模块分析
1.3.1直接插入排序
插入排序重复地将一个新的元素插入到一个拍好序的子线性表中,直到整个线性表排好序。
1.3.2冒泡排序
冒泡排序算法多次遍历数组,在每次遍历中连续比较相邻的元素,如果元素没有按顺序排列,则换它们的值。
1.3.3堆排序
把n个记录存与向量r之中,把它看成是完全二叉树,此时关键字序列不一定满足堆的关系。
堆排序大体分为两步来处理。
初建堆,从堆的定义出发,当i=1、2、······、[2/n]时应该满足ki,<=k2i+1。
所以先取i=[n/2](它一定是第n个节点的双亲编号),将以i结点为根的子书调整为堆,然后令i=i-1。
此时可能会反复调整某些结点,知道i=1为止,堆初步建成。
堆排序,首先输出堆顶的元素(一般是最小值),让堆中最后一个元素上移到原堆顶位置,然后恢复堆。
因为经过第一步输出堆顶元素的操作后,往往破坏了堆关系,所以要恢复堆;重复执行输出堆顶元素、堆尾元素上移和恢复的步骤。
2概要设计
2.1程序结构图
排序综合系统
生成窗口类
堆排序类
冒泡排序类
退出
直接插入排序类
图3.1程序结构图
2.2程序结构图
退出
直接插入排序类
冒泡排序类
堆排序类
图3.2程序流程图
输出数据
3详细设计
3.1开发平台及工具
本次课程设计开发的平台是Windows7。
使用的程序开发语言是Java,编程环境是JDK8,使用的程序开发软件是eclipse。
3.2核心算法设计
3.2.1直接插入排序
假设待排序的记录存放在数组R[n]中,排序过程的某一中间时刻,R被划分为两个子区间[R[1],R[i-1]]和[R[i],R[n-1]],其中:
前一个子区间是已经排好序的有序区;后一个子区间则是当前未排序的部分,不妨称其未无序区.直接插入排序的基本操作是将当前无序区的第一个记录R[i]插入到有序区中适当位置,使得R[1]到R[i]变为新的有序区.
初始时,令i=1,因为一个记录自然是有序的,故R[1]自成为一个有序区,无序区则是R[2]到R[n-1],然后依次将R[2],R[3],…,插入到当前的有序区中,直至i=n-1时,将R[n-1]插入到有序区为止.
现在的问题是:
如何将一个记录R[i](i=2,3,…,n-1)插入到当前的有序区,使得插入后仍保证该区间记录是按关键字有序的.显然,最简单的方法是:
首先,在当前有序区R[1]到R[i-1]中查找R[i]的正确插入位置k(1<=k<=i-1),然后,将R[k]到R[i-1]中记录均后移一个位置,腾出k位置上的空间插入R[i].当然,若R[i]的关键字大于R[1]到R[i-1]中所有记录的关键字,则R[i]就是插入原位置.但是,更为有效的方法是使查找比较操作和记录移动操作交替地进行,具体做法是将待插入记录R[i]的关键字依次与有序区中记录R[j](j=i-1,i-2,…,1)的关键字进行比较,若R[j]的关键字大于R[i]的关键字,则将R[j]后移一个位置;若R[j]的关键字小或等于于R[i]的关键字,则查找过程结束,j+1即为R[i]的插入位置.因为关键字比R[i]的关键字大的记录均已后移,所以j+1的位置已经腾空,只要将R[i]直接插入此位置即可.
程序清单:
publicstaticdouble[]insertionSor(double[]list){
for(inti=1;i doublecurrentElement=list[i]; intk; for(k=i-1;k>=0&&list[k]>currentElement;k--){ list[k+1]=list[k]; } list[k+1]=currentElement; } returnlist; } 3.2.2冒泡排序 设想排序的记录数组R[0]到R[n-1]垂直竖立,将每个记录R[i]看作是重量为R[i]的气泡.根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上“漂浮”,如此反复进行,直到最后任何两个气泡大神轻者在上,重者在下为止. 初始时,R[0]到R[n-1]为无序区,第一趟扫描从该区底部向上依次比较相邻两个气泡的重量,若发现轻者在下,重者在上,则交换两者的位置.本扫描完毕时,最轻的气泡就漂浮到顶上面,即关键字最小的记录被放在最高位置R[0]上.第二趟扫描时,只需扫视R[1]到R[n-1],扫描完毕时,次轻气泡漂浮到R[1]的位置上.一般地,第i趟扫描时,R[0]到R[i-1]和R[i]到R[n-1]分别为当前的有序区和无序区,扫描仍是从无序区底部向上直至该区顶部,扫描完毕时,该区中最轻气泡漂浮到顶部位置R[i]上,结果是R[0]到R[i]变为新的有序区. 因为每一趟排序都使有序区增加了一个气泡,在经过n-1趟排序之后,有序区中就有n-1个气泡,而无序区中气泡的重量总是大于等于有序区中的气泡的重量,所以,整个冒泡排序过程至多需要进行n-1趟排序.但是,若在某一趟排序中未发现气泡位置的交换,则说明待排序的无序区中所有气泡均满足轻者在上,重者在下的原则,因此,冒泡排序过程可在此趟排序后终止.图1.1中,在第四趟(图中第六列)排序过程中就没有气泡交换位置,此时整个文件已达到有序状态. 441111111111111111 334422222222222222 663344333333333333 776633444444444444 887766666655555555 118877777766666666 222288888877777777 555555555588888888 图3.1从下往上的冒泡排序 程序清单: publicstaticvoidbubbleSor(double[]list){ booleanneedNextPass=true; for(intk=1;k needNextPass=false; for(inti=0;i if(list[i]>list[i+1]){ doubletemp=list[i]; list[i]=list[i+1]; list[i+1]=temp; needNextPass=true; } } } } 3.2.3堆排序 把n个记录存与向量r之中,把它看成是完全二叉树,此时关键字序列不一定满足堆的关系。 堆排序大体分为两步来处理。 初建堆,从堆的定义出发,当i=1、2、······、[2/n]时应该满足ki,<=k2i+1。 所以先取i=[n/2](它一定是第n个节点的双亲编号),将以i结点为根的子书调整为堆,然后令i=i-1。 此时可能会反复调整某些结点,知道i=1为止,堆初步建成。 堆排序,首先输出堆顶的元素(一般是最小值),让堆中最后一个元素上移到原堆顶位置,然后恢复堆。 因为经过第一步输出堆顶元素的操作后,往往破坏了堆关系,所以要恢复堆;重复执行输出堆顶元素、堆尾元素上移和恢复的步骤。 程序清单: 见附录 3.3窗口设计 窗口实现三大模块,第一模块是堆排序进行选择,第二模块是输入数据,第三模块是输出数据。 功能是,首先选择一种排序方法,接着输入需要排序的数据,然后输出排序后的数据,最后输出数据的个数和排序所耗的时间。 4设计结果及分析 4.1样例展示 输入100个数字后分别进行直接排序、冒泡排序、堆排序后的结果如下: 4.2数据记录分析 输入不同的数据量N分别在直接排序、冒泡排序、堆排序算法下进行排序,记录所耗时间如下表: 数据个数排序方法 100 500 1000 2000 5000 10000 直接排序 33,552 127,893 473,678 1,863,526 11,418,786 47,611,698 冒泡排序 552,229 779,220 2,461,149 8,015,413 45,312,783 149,498,158 堆排序 185,919 258,944 544,334 1,229,982 3,253,375 6,020,442 通过对上表数据进行分析可知,当数据量N比较小时,如N=<1000,直接排序算法排序速度较快,堆排序次之,冒泡排序较慢;当N.>1500时,堆排序算法排序速度较快,直接排序次之,冒泡排序较慢;但数据量较大时,如N>5000,堆排序据有明显的优势,而冒泡排序这时很明显不可取。 在对算法进行分析是我们知道,对于直接排序、冒泡排序、堆排序,它们理论上的耗时分别为O(n*n)、O(n*n)、O(nlogn),与我们队数据进行分析得出的结论相符。 5结论 在小组成员的分工合作下,本次课程设计完成了对直接插入排序、冒泡排序、堆排序的算法在Java编程语言下的实现,并整合成了一个可以实际应用的软件。 在课程设计的过程中我们不仅对三个算法分别进行了时间复杂度的分析,还我们在所开发的软件上完成了运行测试、数据记录与分析。 由此,我们掌握了三种排序算法的优势和劣势,知道了实际运用排序算法过程中需要注意的问题。 当然,本课程成设计也存在很多的不足,例如,对输入数据量N的跨度过大,测试数据不够多,对所记录数据分析不够透彻,我们可以通过借助数学软件进行改进。 参与课程设计的成员分工如下: 0000: 负责对整个架构进行设计、编写直接排序、冒泡排序、堆排序算法代码、编写软件界面、对课程设计结果进行分析、撰写课程设计报告。 谢辞 通过对算法设计与分析的学习,并在老师的讲解和指导下,我深刻认识到了在程序设计的过程中算法分析的重要性。 正如本次课程设计所展现的,对于解决同一个问题,不同的算法具有不同的优点和缺点。 只有深入地理解算法设计与分析并结合实践,我们才能设计出高效的程序。 在本次课程设计过程中,我们深深的感受到了基础知识的重要性.在以后的学习生活中切不可急于求成而忽略了基础的夯实,对一门系统学科,应该扎实的学习他的每一部分知识,充分利用各种实践环节,切实做到理论联系实践,学以致用。 参考文献 [1]唐策善,李龙澍,黄刘生,《数据结构-用C语言描述》.高等教育出版社,1995 [2]李家同,《算法设计与分析导论(英文版)》.机械工业出版社,2007 [3]梁勇《Java语言程序设计》.机械工业出版社,2016 附录 SortWindonw.java//界面窗口生成类 importjavafx.application.Application; importjavafx.stage.Stage; importjavafx.scene.layout.HBox; importjavafx.scene.layout.VBox; importjavafx.scene.Scene; importjavafx.scene.control.Label; importjavafx.scene.control.RadioButton; importjavafx.scene.control.TextArea; importjavafx.scene.control.TextField; importjavafx.scene.control.ToggleGroup; importjavafx.scene.control.Button; importjavafx.geometry.*; importjava.util.Scanner; publicclassSortWindonwextendsApplication{ RadioButtonrd1=newRadioButton("直接插入排序"); RadioButtonrd2=newRadioButton("冒泡排序"); RadioButtonrd3=newRadioButton("堆排序"); TextAreata1=newTextArea();//数据输入文本区域 TextAreata2=newTextArea();//数据输出文本区域 Buttonbt=newButton("进行排序");//执行排序按钮 TextFieldtextField1=newTextField();//输入数据个数显示文本域 TextFieldtextField2=newTextField();//调用排序算法执行耗时显示文本域 Stringstring=newString();//排序算法返回字符串 Stringstring1=newString();//排序后数据字符串 Stringstring2=newString();//排序算法耗时字符串 Stringstring3=newString();//输入数据个数字符串 intn=0; doubletime=0; /** *生成界面 */ @Override publicvoidstart(StageprimaryStage){ HBoxhBox=newHBox(90); HBoxhBoxend=newHBox(15); VBoxvBox=newVBox(15); LabelLabel1=newLabel("请选择一种排序算法"); LabelLabel2=newLabel("请输入需要排序的数据,数据间用空格分开"); LabelLabel3=newLabel("排序后的数据"); LabelLabel4=newLabel("数据个数"); LabelLabel5=newLabel("排序耗时"); textField1.setPrefColumnCount(4); textField2.setPrefColumnCount(13); ToggleGroupgroup=newToggleGroup(); rd1.setToggleGroup(group); rd2.setToggleGroup(group); rd3.setToggleGroup(group); ta1.setPrefColumnCount(20); ta1.setPrefRowCount(3); ta1.setWrapText(true); ta2.setPrefColumnCount(20); ta2.setPrefRowCount(3); ta2.setWrapText(true); ta2.setEditable(false); hBox.getChildren().addAll(rd1,rd2,rd3); HBoxhBox1=newHBox(); hBox1.getChildren().add(bt); hBox1.setAlignment(Pos.CENTER_RIGHT); hBoxend.getChildren().addAll(Label4,textField1,Label5,textField2); vBox.getChildren().addAll(Label1,hBox,Label2,ta1,hBox1,Label3,ta2,hBoxend); vBox.setPadding(newInsets(15,15,15,15)); insertionSort();//事件触发 Scenescene=newScene(vBox,480,380); primaryStage.setTitle("排序"); primaryStage.setScene(scene); primaryStage.show(); } /**主函数*/ publicstaticvoidmain(String[]args){ Application.launch(args); } /** *事件触发,界面组件与算法交互 */ publicvoidinsertionSort(){ bt.setOnAction(e->{ intn=0; string=ta1.getText();//获取输入的数据 //如果rd1被选中,则执行直接插入排序算法 if(rd1.isSelected()){ string=InsertionSort.insertionSort(string); } //如果rd2被选中,则执行直接插入排序算法 if(rd2.isSelected()){ string=BubbleSort.bubbleSort(string); } //如果rd3被选中,则执行直接插入排序算法 if(rd3.isSelected()){ string=HeapSort.heapSort(string); } Scannerscan1=newScanner(string); //从排序算法返回字符串string中提取算法执行时间time和计算数据的个数n for(inti=0;scan1.hasNextDouble();i++){ time=scan1.nextDouble(); n=n+1; } string2=time+""+"纳秒"; n=n-1; string3=""+n; Scannerscan2=newScanner(string); //从排序算法返回字符串string中提取排序后的数据 for(intj=0;j string1+=scan2.nextDouble()+""; } System.out.println("time: "+time); System.out.println("N为: "+n); textField1.setText(string3); textField2.setText(string2); ta2.setText(string1); string1=""; }); } } InsertionSort.java//直接插入排序算法类 importjava.util.Scanner; publicclassInsertionSort{ /** *直接插入排序 *@paramlist *@return */ publicstaticdouble[]insertionSor(double[]list){ for(inti=1;i doublecurrentElement=list[i]; intk; for(k=i-1;k>=0&&list[k]>currentElement;k--){ list[k+1]=list[k]; } list[k+1]=currentElement; } returnlist; } /** *直接插入排序算法 * *@paramstring *@return */ publicstaticStringinsertionSort(Stringstring){ StringreturnString=""; Scannerscan=newScanner(string); intn=0; doubled=0.0; for(;scan.hasNext();){d=scan.nextDouble();n=n+1;} double[]list=newdouble[n]; Scannerscanner=newScanner(string); for(inti=0;scanner.hasNext();i++) { list[i]=scanner.nex
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 冒泡 排序 选择 算法 课程设计 汇总
![提示](https://static.bdocx.com/images/bang_tan.gif)