1、最原始的,每一个都循环一次,双循环来进行排序。外部循环控制所有的回合,内部循环代表每一轮的冒泡处理,先进行元素比较,再进行元素交换,缺点性能较差,效率不高, public static void testSort(){ int [] array = new int []{ 5 , 8 , 6 , 3 , 9 , 2 , 1 , 7 }; int tmp=0; for (int i = 0; i < array.length; i++) { for (int j = 0; jarray[j+1]){ tmp=array[j+1]; array[j+1]=array[j]; array[j]=tmp; } } } System.out.println(Arrays.toString(array)); }
2、改进版
每次循环都会将最大的数字移动到最右边,最后两个数不需要比较,所以实际内循环不需要(array.length-1)次,实际上内循环次数只需要(array.length-i-1)就可以了
public static void testSort(){ int [] array = new int []{ 5 , 8 , 6 , 3 , 9 , 2 , 1 , 7 }; int tmp=0; for (int i = 0; i < array.length; i++) { for (int j = 0; jarray[j+1]){ tmp=array[j+1]; array[j+1]=array[j]; array[j]=tmp; } } } System.out.println(Arrays.toString(array)); }
3、效率进一步优化
有时候经过几轮循环以后排序已经是按照从小到大的顺序了,所以后面都不需要进行排序了
public static void testSort(){ int [] array = new int []{ 5 , 8 , 6 , 3 , 9 , 2 , 1 , 7 }; int tmp=0; for (int i = 0; i < array.length; i++) { boolean isSorted = true ; for (int j = 0; jarray[j+1]){ tmp=array[j+1]; array[j+1]=array[j]; array[j]=tmp; isSorted=false; } } if(isSorted){ break; } } System.out.println(Arrays.toString(array)); }
4、最终版
按照现有的逻辑,有序区的长度和排序的轮数是相等的。比如第一轮排序过后的有序区长度是1,第二轮排序过后的有序区长度是2 ......实际上,数列真正的有序区可能会大于这个长度,比如例子中仅仅第二轮,后面5个元素实际都已经属于有序区。因此后面的许多次元素比较是没有意义的。
我们可以在每一轮排序的最后,记录下最后一次元素交换的位置,那个位置也就是无序数列的边界,再往后就是有序区了。
private static void sort () { int [] array = new int []{ 5 , 8 , 6 , 3 , 9 , 2 , 1 , 7 }; int tmp=0; int lastExchangeIndex=0; int sortBorder = array.length-1; for (int i = 0; i < array.length; i++) { boolean isSorted=true; for (int j = 0; j < sortBorder ; j++) { if(array[j]>array[j+1]){ tmp=array[j+1]; array[j+1]=array[j]; array[j]=tmp; isSorted=false; lastExchangeIndex=j; } } sortBorder=lastExchangeIndex; if(isSorted){ break; } } System.out.println(Arrays.toString(array)); }
这一版代码中,sortBorder就是无序数列的边界。每一轮排序过程中,sortBorder之后的元素就完全不需要比较了,肯定是有序的