冒泡排序基本思想:
通过对待排序序列从前往后,依次比较相邻元素,若发现逆序,则交换位置,使较大的元素逐渐从前往后移动,就像水底的气泡一样逐渐向上冒。
假如一个序列有n个元素,具体实现步骤如下:
第一轮比较:第1个元素和第2个元素比较,如果逆序,则交换两个元素的位置,否则不交换;接着第2个元素与第3个元素比较,如果逆序则交换,直到比较第n-1个元素和第n个元素结束,此时,整个序列的最大值会移动到最后,这是第一轮比较;
第二轮比较:仍然从第1个元素和第2个元素开始比较,过程与之前一样,直到比较第n-2个元素和第n-1个元素结束,此时前n-1个元素中的最大值就会移动到第n-1的位置;
依次类推,需要进行n-1轮比较,因为最后序列的第一个元素不需要比较,肯定是最小的,这样就形成了一个有序序列。
冒泡排序java代码实现:
public class BubbleSort {
/**
* 未优化,常规冒泡排序
*
* @param nums
*/
public static void bubbleSort(int[] nums) {//3,1,4,2,5
int temp;
for (int i = 0; i < nums.length - 1; i++) {//经过nums.length - 1轮比较
for (int j = 0; j < nums.length - i - 1; j++) {//n-1,n-2,n-3,...,1 = [(n-1)+1]*(n-1)/2=1/2n^2-1/2n=O(n^2)
if (nums[j] > nums[j + 1]) {
temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
}
}
冒泡排序优化:
经过以上分析会发现一个问题,一个长度为n的序列一定需要经过n-1轮比较吗?不一定,如果某一轮的比较发现没有进行任何相邻元素之间的交换,说明这个序列已经是有序的了,不需要再进行下一轮的比较,因此如果加一个判断条件,发现比较完一轮之后没有元素交换,则退出循环,这样排序效率就可以得到提升。
冒泡排序优化后代码:
public class BubbleSort {
/**
* 优化后
*
* @param nums
*/
public static void bubbleSort2(int[] nums) {//3,1,4,2,5
int temp;
boolean flag = false;//用于判断某一轮比较是否发生了元素交换
for (int i = 0; i < nums.length - 1; i++) {//
for (int j = 0; j < nums.length - i - 1; j++) {//n-1,n-2,n-3,...,1 = [(n-1)+1]*(n-1)/2=1/2n^2-1/2n=O(n^2)
if (nums[j] > nums[j + 1]) {
flag = true;
temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
if (!flag) {//这一轮没有进行任何交换
break;
} else {
flag = false;
}
}
}
}
冒泡排序时间复杂度
最坏情况下:需要比较(n-1) + (n-2) + (n-3) + … + 1 = n*(n-1)/2次,所以复杂度是O(n2).