冒泡排序和快速排序都是属于交换排序的一种。所谓交换,就是根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置。
冒泡排序算法的基本思想就是:在待排序表中,从后往前(或从前往后)两两比较相邻元素的值,若逆序则交换它们,知道序列比较完,这就是一趟冒泡。此时这个元素就在它的最终位置了,下一趟冒泡时,其不再参与。每趟冒泡的结果都是把序列中的一个元素放到了序列的最终位置。
冒泡排序中,我们使用了常数个辅助单元,因此空间复杂度为 O(1);
当序列有序时,显然我们只需要比较 n - 1 次,交换 0 次,从而最好的情况下的时间复杂度是 O(n)。
如果序列逆序,则需进行 n - 1 趟冒泡操作,第 i 趟时要进行 n - i 次关键字的比较,而每一次比较都必须移动元素3次来交换元素位置。所以:
比较次数 = n(n-1)/2 ==> 从i=1到n-1的对(n-i)的求和所得
移动次数 = 3n(n-1)/2 ==> 从i-1到n-1的对3(n-i)的求和所得
所以最坏情况下时间复杂度为 O(n^2),故平均时间复杂度为 O(n^2)。
冒泡排序的代码如下:
/**
* 从小到大排序
* @param {number[]} nums
* @return {number[]}
*/
function bubbleSort(nums) {
let flag = false; //flag来控制一趟排序后是否有交换元素的操作,如果flag还是false就说明序列已经有序了
for (let i = 0; i < nums.length - 1; i++) {
flag = false;
for (let j = nums.length - 1; j > i; j--) {
if (nums[j - 1] > nums[j]) {
[nums[j - 1], nums[j]] = [nums[j], nums[j - 1]];
flag = true;
}
}
if (!flag) {
break;
}
}
return nums;
}
小结:
- 冒泡排序是稳定的排序算法
- 时间复杂度为 O(n^2)
- 空间复杂度为 O(1)
- 每一趟冒泡都会将一个元素放到了其最终所在的位置