一、思路
在进行冒泡排序(升序)时,需要将数组中的元素(len)两两进行比较,如果前面的元素大于后面的元素的话,则交换两个数,否则,比较下一个元素和它下一个元素的大小,依次执行,执行一次循环结束之后,可以找到当前数组中最大的一个元素,将其排到了最后面,然后问题规模变小,然后找出len-1个元素里的最大值,使之成为第二大元素,依次执行,需要在外层嵌套一层循环。
二、优化
如果数组中的数据已经是排好序的,那么就不需要遍历那么多次了,定义一个标志位,如果没有执行交换,如果一轮下来没有进行数据交换,则证明数据已经拍好顺序了,此时,则直接跳出循环。
三、图解
四、代码实现
有数组int arr[] = {23,19,33,55,27},按照小到大的顺序排序
两种思路
思路一、arr[i]与arr[i+1]比较,如果前者比后者大,则交换二者的位置,这样两两调换后,一轮下来,最大的会被放到arr[len-1]的位置。每一轮i都从0开始,当第j轮排序之后就有最后面的j个数字,因为它是最大的,所以每轮的最后都不用理他了,也就是 arr.length-1-j 往后的数就不用管了,比如第一轮开始的时候,数组共有四个数字,j=0,那么 arr.length-1-j =4,也就是说下表3以后的就可以不用管了,因为下表4以后,没有数字,所以,第一轮所有的数字都要参与比较,第二轮开始的时候,已经比较结束一轮了。此时j=1,所以 arr.length-1-j = 3,也就是说下表3之后的元素都不用管了,已经是最大的了,因为两两比较之后55会到arr[4]的位置。
public static int[] sort(int[] arr){ //外层决定比较的轮数 for (int i = 0;i < arr.length -1;i++){ //内层决定每轮比较的次数 for (int j = 0;j < arr.length -1 -i;j++){ //小->大 if (arr[j] > arr[j+1]){ int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } return arr; }
思路二、从后往前比较。也就是说先用27跟55比较,再跟33比较,再跟19比较,再跟23比较,发现19是最小的,将其放到最前面(index=0)的位置,然后j=1,也就是第二轮,就不用看下标为0了,因为它是最小的了,然后接着比较
public static int[] sort2(int[] arr){ //外层决定比较的轮数 for (int i = 0;i < arr.length-1;i ++){ //从后往前比较,倒数第二个与倒数第一个比较,所以这里j=arr.length-2 for (int j = (arr.length - 2); j >= i;j--){ if (arr[j] > arr[j+1]){ int tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } } return arr; }
注:这里的j为什么等于arr.length-2呢?因为length=5,我最多让下标2和下标3的数字比较(j+1最大等于3),也就是j最大等于2,2和2+1比较,然后0和1比较。
五、时间复杂度分析
最好的情况下时间复杂度为0(n):当待排序的数据已经按照顺序排好的情况下
最坏的情况下时间复杂度为0(n^2):因为要比较n-1趟,每一趟要比较(n-1-i)次