冒泡排序
起泡排序
执行流程(升序)
- 从头开始比较每一对相邻元素,如果第一个比第二大,就交换他们的位置–执行完一轮后,最末尾那个元素就是最大的元素
- 忽略第一步中曾经找到的最大元素,重复执行步骤一,知道全部元素有序
步骤演示
代码实现
// java
for (int end = array.length - 1; end > 0; end--) {
// 外层循环控制循环次数
// 内层循环进行每一轮的比较
for (int begin = 1; begin <= end; begin++) {
// 如果当前数比它前一个数小,则交换
if (array[begin] < array[begin - 1]) {
// 交换
int temp = array[begin];
array[begin] = array[begin - 1];
array[begin - 1] = temp;
}
}
}
优化方案一
如果序列已经完全有序,可以提前终止排序算法,不需要在进行比较
只需要增加一个控制变量即可
- 代码
// java
for (int end = array.length - 1; end > 0; end--) {
// 外层循环控制循环次数
// 内层循环进行每一轮的比较
boolean sorted = true; // 判断是否已经有序的标志
for (int begin = 1; begin <= end; begin++) {
// 如果当前数比它前一个数小,则交换
if (array[begin] < array[begin - 1]) {
// 交换
int temp = array[begin];
array[begin] = array[begin - 1];
array[begin - 1] = temp;
sorted = false; // 如果运行到这一步,说明有交换,说明不是有序的
}
if (sorted) break; // 如果有序 无需进行直接退出
}
}
此优化方式只针对于基本有序的数组,如果数组本就是无序的,此优化方案其实没有上一个方法好
优化方案二
如果序列尾部已经局部有序,可以记录最后一次交换的位置,减少比较次数
- 代码
// java
for (int end = array.length - 1; end > 0; end--) {
// 外层循环控制循环次数
// 内层循环进行每一轮的比较
int sortedIndex = 1; // 用于记录最后一次交换的位置
for (int begin = 1; begin <= end; begin++) {
// 如果当前数比它前一个数小,则交换
if (array[begin] < array[begin - 1]) {
// 交换
int temp = array[begin];
array[begin] = array[begin - 1];
array[begin - 1] = temp;
sortedIndex = begin; // 记录
}
end = sortedIndex; // 减少比较次数
}
}
总结
冒泡排序属于稳定算法,原地算法(不依赖额外的资源或者依赖少数的额外资源,仅依靠输出来覆盖输入)
空间复杂度为O(1)的都可以认为是原地算法