标签:一次循环 提升 [] 反序 性能 嵌套循环 ima 结束 正序
时间复杂度 O(n2),里层循环每趟比较第 j 项和第 j+1项,如果前项大于后项,则发生交换。缺点是每次比较后都可能发生交换,交换次数太多了,值从小到大。
通俗概述:依次比较相邻两关键字,如果反序则立即发生交换,如果正序则继续比较下一个相邻项,双重嵌套循环实现
参考代码:
package com.tyut; import java.util.Arrays; /** * 冒泡排序:利用双重循环,如果前一个数比后一个数大,则发生交换,每次比较都发生交换 优化版:添加flag标记,循环外定义flag标记为true,进入循环后flag设为false,
若一次循环后发生了交换则将flag设为ture,进入下次循环;若整次循环只发生比较未发生交换,则说明数组已经有序,后续循环比较则不必要了,减少比较次数,提升性能 */ public class BubbleSort { public static void bubbleSort(int[] arrs) { int temp = 0; boolean flag=true;//用flag作标记,当没有发生交换的时候,说明数组已经是有序的了。 for (int i = 0; i < arrs.length - 1&&flag; i++) { flag=false;//flag标记初始化为false; for (int j = 0; j < arrs.length - i - 1; j++) { //判断当前项是否大于后一项 if (arrs[j] > arrs[j + 1]) {//是,则发生交换 temp = arrs[j]; arrs[j] = arrs[j + 1]; arrs[j + 1] = temp; flag=true;//发生交换flag标记设为true } } } } public static void main(String[] args) { int[] arr=new int[]{2,6,5,4,2,4,6,9,7}; System.out.println(Arrays.toString(arr)); bubbleSort(arr); System.out.println(Arrays.toString(arr)); } }
简单选择排序(Simple Selection Sort):就是通过n-1次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和i(1<=i<=n)个记录交换值
时间复杂度 O(n2),在冒泡排序的基础上,只不过每次比较后,将保存最小值的索引指向小值,在一次循环结束时,将最小值与循环首项发生交换。整体分为已排序和未排序两部分,值从小到大。
注意区别:冒泡排序跟直接选择排序都是依次比较相邻的记录,但是冒泡排序是一有反序立即交换,而直接插入排序则是出现反序将最小值记录下来,最后再发生交换。
参考代码:
package com.tyut; import java.util.Arrays; /** * 简单选择排序:在待排序中找出最小值,然后放到已排序的末尾 * 利用双重for循环,找出最小值,再发生一次交换 */ public class SelectionSort { //需要遍历获得最小值的次数 //要注意一点,当要排序N个数,已经经过N-1次遍历后,已经是有序数列 public static void selectSort(int[] arrs) { for (int i = 0; i < arrs.length - 1; i++) { int temp=0; int index=i;//用来保存最小的索引,初始指向当前第i项 //从未排序数中找出最小值,这里最大索引应该是数组最后一位即length-1 for (int j = i+1; j <arrs.length; j++) { //如果后面的值比索引值还小,则将索引指向最小值 if (arrs[j]<arrs[index]){ index=j; } } //已经找到最小值,然后将最小值放到已排序的末尾 temp=arrs[i]; arrs[i]=arrs[index]; arrs[index]=temp; } } public static void main(String[] args) { int[] arrs=new int[]{2,6,8,99,4,46,4,5}; System.out.println(Arrays.toString(arrs)); selectSort(arrs); System.out.println(Arrays.toString(arrs)); } }
时间复杂度O(n2),利用双重for循环,从第二个数开始遍历,然后保存待插入的数,这样有序部分则可以向后覆盖一个位置,然后里层循环 j >= 0 && temp < arrs[j] 找到合适的位置后,只需要将待插入的数插入即可。
参考代码:
package com.tyut; import java.util.Arrays; /** * 插入排序: */ public class InsertionSort { public static void insertSort(int[] arrs) { //第一个肯定是有序的,所以从第二个数开始遍历 for (int i = 1 ;i < arrs.length - 1; i++) { int j=0; int temp = arrs[i];//取出第i给数,和前i-1个数比较,插入合适位置。 //因为前i-1个数都是从小到大的有序序列,所以只要当前比较的数arr[j]比temp大,就把这个数后移一位 for (j = i - 1; j >= 0 && temp < arrs[j]; j--) { arrs[j+1]=arrs[j];//因为第i个数已经保存为temp,所以可以向后覆盖 } //将第i个值插入到合适位置,因为交换结束后再自减运算,所以这里需要+1 arrs[j+1]=temp; } } public static void main(String[] args) { int[] arrs=new int[]{2,6,5,2,3,4,3,0,6}; System.out.println(Arrays.toString(arrs)); insertSort(arrs); System.out.println(Arrays.toString(arrs)); } }
时间复杂度为O(nlogn),该方法因DL.Shell于1959年提出而得名。超越了O(n2)的算法的历史。他是在直接插入排序的增强,将记录按步长gap分组,然后在分组内进行直接插入排序。不稳定算法。
参考代码:
package com.tyut; import java.util.Arrays; /** * 希尔排序:在直接插入排序的基础上,将记录按步长进行分组 * 所以可知,直接插入排序相当与步长为1的希尔排序 */ public class ShellSort { public static void shellSort(int[] arrs) { //初始化步长为数组长度的一半 int gap = arrs.length / 2; //循环结束条件,当gap<1是,循环结束,即排序结束 while (gap >= 1) { //把距离为gap的元素编为一个组,扫描所有组 for (int i = gap; i < arrs.length; i++) { int j = 0; int temp = arrs[i];//保存待插入元素,以便组内元素向后移动覆盖 //对距离为gap的组内元素进行直接选择排序 for (j = i - gap; j >= 0 && temp < arrs[j]; j = j - gap) { arrs[j+gap]=arrs[j]; } //将待插入元素插入合适位置 arrs[j+gap]=temp; } //一次循环结束,所有分组均已完成直接选择排序,则可将将距离缩小为原本的一半 gap=gap/2; } } public static void main(String[] args) { int[] arrs=new int[]{3,6,8,4,6,7,9,8,7,5}; System.out.println(Arrays.toString(arrs)); shellSort(arrs); System.out.println(Arrays.toString(arrs)); } }
![](D:\百度云\Resource\img_algotirhm\Shell-Sort.png)
标签:一次循环 提升 [] 反序 性能 嵌套循环 ima 结束 正序
原文地址:https://www.cnblogs.com/turbosha/p/9970904.html