Java各种排序算法总结.docx
- 文档编号:8729924
- 上传时间:2023-05-14
- 格式:DOCX
- 页数:36
- 大小:54.87KB
Java各种排序算法总结.docx
《Java各种排序算法总结.docx》由会员分享,可在线阅读,更多相关《Java各种排序算法总结.docx(36页珍藏版)》请在冰点文库上搜索。
Java各种排序算法总结
排序是程序开发中一种非常常见的操作,对一组任意的数据元素(或记录)经过排序操作后,就可以把他们变成一组按关键字排序的有序队列。
对一个排序算法来说,一般从下面3个方面来衡量算法的优劣:
1.时间复杂度:
它主要是分析关键字的比较次数和记录的移动次数。
2.空间复杂度:
分析排序算法中需要多少辅助内存。
3.稳定性:
若两个记录A和B的关键字值相等,但是排序后A,B的先后次序保持不变,则称这种排序算法是稳定的;反之,就是不稳定的。
就现有的排序算法来看,排序大致可分为内部排序和外部排序。
如果整个排序过程不需要借助外部存储器(如磁盘等),所有排序操作都是在内存中完成,这种排序就被称为内部排序。
如果参与排序的数据元素非常多,数据量非常大,计算无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘),这种排序就被称为外部排序。
外部排序最常用算噶是多路归并排序,即将原文件分解称多个能够一次性装入内存的部分,分别把每一部分调入内存完成排序,接下来再对多个有序的子文件进行归并排序。
就常用的内部排序算法来说,可以分为以下几类:
∙选择排序(直接选择排序,堆排序)
∙交换排序(冒泡排序,快速排序)
∙插入排序(直接插入排序,折半插入排序,Shell排序)
∙归并排序
∙桶式排序
∙基数排序
Java排序算法
(二):
直接选择排序
直接选择排序的基本操作就是每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完,它需要经过n-1趟比较。
算法不稳定,O
(1)的额外的空间,比较的时间复杂度为O(n^2),交换的时间复杂度为O(n),并不是自适应的。
在大多数情况下都不推荐使用。
只有在希望减少交换次数的情况下可以用。
基本思想
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果:
①初始状态:
无序区为R[1..n],有序区为空。
②第1趟排序
在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R[1]交换,使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
③第i趟排序
第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R(1≤i≤n-1)。
该趟排序从当前无序区中选出关键字最小的记录R[k],将它与无序区的第1个记录R交换,使R[1..i]和R分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
这样,n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。
算法实现
viewplain
1.public class SelectSortTest{
2.
3.public static void main(String[]args){
4.int[]data= new int[]{ 5, 3, 6, 2, 1, 9, 4, 8, 7 };
5.print(data);
6.selectSort(data);
7.print(data);
8.}
9.
10.public static void swap(int[]data, int i, int j){
11.if (i==j){
12.return;
13.}
14.data[i]=data[i]+data[j];
15.data[j]=data[i]-data[j];
16.data[i]=data[i]-data[j];
17.}
18.
19.public static void selectSort(int[]data){
20.for (int i= 0;i 21.int minIndex=i; //记录最小值的索引 22.for (int j=i+ 1;j 23.if (data[j] 24.minIndex=j; //若后面的元素值小于最小值,将j赋值给minIndex 25.} 26.} 27.if (minIndex! =i){ 28.swap(data,i,minIndex); 29.print(data); 30.} 31.} 32.} 33. 34.public static void print(int[]data){ 35.for (int i= 0;i 36.System.out.print(data[i]+ "\t"); 37.} 38.System.out.println(); 39.} 40.} 运行结果: viewplain 1.536219487 2.136259487 3.126359487 4.123659487 5.123459687 6.123456987 7.123456789 8.123456789 Java排序算法(三): 堆排序 堆积排序(Heapsort)是指利用堆积树(堆)这种资料结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。 堆排序是不稳定的排序方法,辅助空间为O (1),最坏时间复杂度为O(nlog2n),堆排序的堆序的平均性能较接近于最坏性能。 堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。 (1)用大根堆排序的基本思想 ①先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区 ②再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key ③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。 然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。 …… 直到无序区只有一个元素为止。 (2)大根堆排序算法的基本操作: ①初始化操作: 将R[1..n]构造为初始堆; ②每一趟排序的基本操作: 将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。 注意: ①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。 ②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。 堆排序和直接选择排序相反: 在任何时刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。 代码实现: viewplaincopytoclipboard 1.public class HeapSortTest{ 2. 3.public static void main(String[]args){ 4.int[]data5= new int[]{ 5, 3, 6, 2, 1, 9, 4, 8, 7 }; 5.print(data5); 6.heapSort(data5); 7.System.out.println("排序后的数组: "); 8.print(data5); 9.} 10. 11.public static void swap(int[]data, int i, int j){ 12.if (i==j){ 13.return; 14.} 15.data[i]=data[i]+data[j]; 16.data[j]=data[i]-data[j]; 17.data[i]=data[i]-data[j]; 18.} 19. 20.public static void heapSort(int[]data){ 21.for (int i= 0;i 22.createMaxdHeap(data,data.length- 1 -i); 23.swap(data, 0,data.length- 1 -i); 24.print(data); 25.} 26.} 27. 28.public static void createMaxdHeap(int[]data, int lastIndex){ 29.for (int i=(lastIndex- 1)/ 2;i>= 0;i--){ 30.//保存当前正在判断的节点 31.int k=i; 32.//若当前节点的子节点存在 33.while (2 *k+ 1 <=lastIndex){ 34.//biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点 35.int biggerIndex= 2 *k+ 1; 36.if (biggerIndex 37.//若右子节点存在,否则此时biggerIndex应该等于lastIndex 38.if (data[biggerIndex] 39.//若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的值 40.biggerIndex++; 41.} 42.} 43.if (data[k] 44.//若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k 45.swap(data,k,biggerIndex); 46.k=biggerIndex; 47.} else { 48.break; 49.} 50.} 51.} 52.} 53. 54.public static void print(int[]data){ 55.for (int i= 0;i 56.System.out.print(data[i]+ "\t"); 57.} 58.System.out.println(); 59.} 60. 61.} 运行结果: viewplaincopytoclipboard 1.5 3 6 2 1 9 4 8 7 2.3 8 6 7 1 5 4 2 9 3.2 7 6 3 1 5 4 8 9 4.4 3 6 2 1 5 7 8 9 5.4 3 5 2 1 6 7 8 9 6.1 3 4 2 5 6 7 8 9 7.2 3 1 4 5 6 7 8 9 8.1 2 3 4 5 6 7 8 9 9.1 2 3 4 5 6 7 8 9 10.1 2 3 4 5 6 7 8 9 11.排序后的数组: 12.1 2 3 4 5 6 7 8 9 整个排序过程图解: (待有时间再补充...) Java排序算法(四): 冒泡排序 冒泡排序是计算机的一种排序方法,它的时间复杂度为O(n^2),虽然不及堆排序、快速排序的O(nlogn,底数为2),但是有两个优点: 1.“编程复杂度”很低,很容易写出代码; 2.具有稳定性,这里的稳定性是指原序列中相同元素的相对顺序仍然保持到排序后的序列,而堆排序、快速排序均不具有稳定性。 不过,一路、二路归并排序、不平衡二叉树排序的速度均比冒泡排序快,且具有稳定性,但速度不及堆排序、快速排序。 冒泡排序是经过n-1趟子排序完成的,第i趟子排序从第1个数至第n-i个数,若第i个数比后一个数大(则升序,小则降序)则交换两数。 冒泡排序算法稳定,O (1)的额外的空间,比较和交换的时间复杂度都是O(n^2),自适应,对于已基本排序的算法,时间复杂度为O(n)。 冒泡算法的许多性质和插入算法相似,但对于系统开销高一点点。 排序过程 设想被排序的数组R[1..N]垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上"漂浮",如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。 代码实现 viewplain 1.public class BubbleSortTest{ 2. 3.public static void main(String[]args){ 4.int[]data5= new int[]{ 5, 3, 6, 2, 1, 9, 4, 8, 7}; 5.print(data5); 6.bubbleSort(data5); 7.System.out.println("排序后的数组: "); 8.print(data5); 9.} 10. 11.public static void swap(int[]data, int i, int j){ 12.if (i==j){ 13.return; 14.} 15.data[i]=data[i]+data[j]; 16.data[j]=data[i]-data[j]; 17.data[i]=data[i]-data[j]; 18.} 19. 20.public static void bubbleSort(int[]data){ 21.for (int i= 0;i 22.//记录某趟是否发生交换,若为false表示数组已处于有序状态 23.boolean isSorted= false; 24.for (int j= 0;j 25.if (data[j]>data[j+ 1]){ 26.swap(data,j,j+ 1); 27.isSorted= true; 28.print(data); 29.} 30.} 31.if (! isSorted){ 32.//若数组已处于有序状态,结束循环 33.break; 34.} 35.} 36.} 37. 38.public static void print(int[]data){ 39.for (int i= 0;i 40.System.out.print(data[i]+ "\t"); 41.} 42.System.out.println(); 43.} 44. 45.} 运行结果 viewplain 1.5 3 6 2 1 9 4 8 7 2.3 5 6 2 1 9 4 8 7 3.3 5 2 6 1 9 4 8 7 4.3 5 2 1 6 9 4 8 7 5.3 5 2 1 6 4 9 8 7 6.3 5 2 1 6 4 8 9 7 7.3 5 2 1 6 4 8 7 9 8.3 2 5 1 6 4 8 7 9 9.3 2 1 5 6 4 8 7 9 10.3 2 1 5 4 6 8 7 9 11.3 2 1 5 4 6 7 8 9 12.2 3 1 5 4 6 7 8 9 13.2 1 3 5 4 6 7 8 9 14.2 1 3 4 5 6 7 8 9 15.1 2 3 4 5 6 7 8 9 16.排序后的数组: 17.1 2 3 4 5 6 7 8 9 18. Java排序算法(五): 快速排序 快速排序是一个速度非常快的交换排序算法,它的基本思路很简单,从待排的数据序列中任取一个数据(如第一个数据)作为分界值,所有比它小的数据元素放到左边,所有比它大的数据元素放到它的右边。 经过这样一趟下来,该序列形成左右两个子序列,左边序列中的数据元素的值都比分界值小,右边序列中数据元素的值都比分界值大。 接下来对左右两个子序列进行递归排序,对两个子序列重新选择中心元素并依此规则调整,直到每个元素子表的元素只剩下一个元素,排序完成。 思路: 1.定义一个i变量,i变量从左边第一个索引开始,找大于分界值的元素的索引,并用i来记录它。 2.定义一个j变量,j变量从右边第一个索引开始,找小于分界值的元素的索引,并用j来记录它。 3.如果i 重复执行以上1,2,3步,直到i>=j,可以判断j左边的数据元素都小于分界值,j右边的数据元素都大于分界值,最后将分界值和j索引处的元素交换即可。 时间复杂度 最好情况(每次总是选到中间值作枢轴)T(n)=O(nlogn) 最坏情况(每次总是选到最小或最大元素作枢轴) 做n-1趟,每趟比较n-i次,总的比较次数最大: [O(n²)] 平均时间复杂度为: : T(n)=O(nlogn) 代码实现: viewplain 1.package sort; 2. 3.public class QuickSortTest{ 4. 5.public static void main(String[]args){ 6.int[]data= new int[]{ 5, 3, 6, 2, 1, 9, 4, 8, 7 }; 7.print(data); 8.quickSort(data, 0,data.length- 1); 9.System.out.println("排序后的数组: "); 10.print(data); 11.} 12. 13.public static void swap(int[]data, int i, int j){ 14.if (i==j){ 15.return; 16.} 17.data[i]=data[i]+data[j]; 18.data[j]=data[i]-data[j]; 19.data[i]=data[i]-data[j]; 20.} 21. 22.public static void quickSort(int[]data, int start, int end){ 23.if (start>=end) 24.return; 25.//以起始索引为分界点 26.int pivot=data[start]; 27.int i=start+ 1; 28.int j=end; 29.while (true){ 30.while (i<=end&&data[i] 31.i++; 32.} 33.while (j>start&&data[j]>pivot){ 34.j--; 35.} 36.if (i 37.swap(data,i,j); 38.} else { 39.break; 40.} 41.} 42.//交换j和分界点的值 43.swap(data,start,j); 44.print(data); 45.//递归左子序列 46.quickSort(data,start,j- 1); 47.//递归右子序列 48.quickSort(data,j+ 1,end); 49.} 50. 51.public static void print(int[]data){ 52.for (int i= 0;i 53.System.out.print(data[i]+ "\t"); 54.} 55.System.out.println(); 56.} 57. 58.} 运行结果: viewplain 1.5 3 6 2 1 9 4 8 7 2.1 3 4 2 5 9 6 8 7 3.1 3 4 2 5 9 6 8 7 4.1 2 3 4 5 9 6 8 7 5.1 2 3 4 5 7 6 8 9 6.1 2 3 4 5 6 7 8 9 7.排序后的数组: 8.1 2 3 4 5 6 7 8 9 9. Java排序算法(六): 直接插入排序 直接插入排序的基本操作就是将待排序的数据元素按其关键字值的大小插入到前面的有序序列中。 直接插入的时间效率并不高,如果在最坏的情况下,所有元素的比较次数总和为(0+1+...+n-1)=O(n^2)。 其他情况下也要考虑移动元素的次数,故时间复杂度为O(n^2) 直接插入空间效率很好,只需要1个缓存数据单元,也就是说空间复杂度为O (1). 直接插入排序是稳定的。 直接插入排序在数据已有一定顺序的情况下,效率较好。 但如果数据无规则,则需要移动大量的数据,其效率就与冒泡排序法和选择排序法一样差了。 算法描述 对一个有n个元素的数据序列,排序需要进行n-1趟插入操作: 第1趟插入,将第2个元素插入前面的有序子序列--此时前面只有一个元素,当然是有序的。 第2趟插入,将第3个元素插入前面的有序子序列,前面2个元素是有序的。 第n-1趟插入,将第n个元素插入前面的有序子序列,前面n-1个元素是有序的。 代码实现 viewplain 1.package sort; 2. 3.public class InsertSortTest{ 4.public static int count= 0; 5. 6.public static void main(String[]args){ 7. 8.int[]data= new int[]{ 5, 3, 6, 2, 1, 9, 4, 8, 7 }; 9.print(data); 10.insertSort(data); 11.print(data); 12. 13.} 14. 15.public static void insertSort(int[]data){ 16.for (int i= 1;i 17.//缓存i处的元素值 18.int tmp=data[i]; 19.if (data[i] 20.int j=i
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java 各种 排序 算法 总结