气泡排序、两种实现方式和优化
冒泡排序
基本原理
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
比如:第一次排序,内层循环两两对比互换位置,将一个最值放到最后,第二次排序,内层循环又继续通过两两对比互换位置,将剩下的值中的最值放到倒数第二个位置,因为互换位置是通过两两对比的方式,所以交换次数的时间复杂度是O(n²)
稳定性
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,是不会再交换的如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也还是不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。 总结:冒泡排序是相邻元素两两对比,交换也发生在这两个元素之间。只有两个元素大小不一样才会交换,相邻的相同元素大小一样不会交换位置,相同的元素不相邻,后面通过两两对比交换变成了相邻了,也还是大小一样,不会交换位置!!!假设只有两个元素,且这两个元素相等(只有两个那也代表他们必相邻),他们两两对比,左边的不大/小于右边的,因此不会交换位置!所以冒泡排序是稳定的。
举例子,看代码最直接,假设两个相同元素:[1,1],arr[j] < arr[j + 1]压根就不会成立,因此这两个相同元素不会互换位置,故稳定 function bubbleSort(arr) { for (var i = 0; i < arr.length; i++) { for (var j = 0; j < arr.length; j++) { if (arr[j] < arr[j + 1]) { var temp = arr[j] arr[j] = arr[j + 1] arr[j + 1] = temp } } } return arr }
复杂度
时间复杂度:O(n²)
实现
实现1
var arr = [1, 2, 3, 4, 5, 6];
// var arr = [6, 5, 4, 3, 2, 1];
// var arr = [32, 14, 6, 9, 20, 58];
// 外层for循环控制互换多少轮
// 里层for循环控制每一轮互换多少次
// 没有任何优化,需要固定循环arr.length*arr.length次数
function bubbleSort(arr) {
// 外层for循环互换6轮
for (var i = 0; i < arr.length; i++) {
// 内层for循环每轮互换6次
for (var j = 0; j < arr.length; j++) {
console.log(1)
// 如果第一个比第二个大,则交换位置,最终就是:小->大
// if (arr[j] >arr[j + 1]) {
// 如果第一个比第二个小,则互换位置,最终就是:大->小
if (arr[j] < arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
优化1
// 优化越界问题
// 因为里层for循环会下标+1,当里层j=arr.length+1时,值为undefined
// 优化后,需要固定循环arr.length*(arr.length-1)次数
function bubbleSort1(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr.length - 1; j++) {
console.log(1)
if (arr[j] < arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
优化2
/**
* 每次外层循环后,里层循环不应该固定循环arr.length-1次,
* 因为每次外层循环后,里层循环都会得出一个最终的最值,
* 后面的里层循环,这个最值不用重复的继续循环
* 所以应该每次都相对应的减少里层的循环次数
* 第一轮内循环互换了5次,第二轮4次,第三轮3次,第四轮2次,第五轮1次,第六轮0次
* 优化后,需要固定循环(arr.length*(arr.length-1))/2次数
*/
function bubbleSort2(arr) {
for (var i = 0; i < arr.length; i++) {
// console.log(i)
// 互换过的下次就不互换,即每次内层循环次数随着外层越来越小
// 第一轮内层循环互换arr.length - 1 - 0次,即5次
// 第二轮内层循环互换arr.length - 1 - 1次,即4次
// 第三轮内层循环互换arr.length - 1 - 2次,即3次
// 第四轮内层循环互换arr.length - 1 - 3次,即2次
// 第五轮内层循环互换arr.length - 1 - 5次,即1次
// 第六轮内层循环互换arr.length - 1 - 6次,即0次
for (var j = 0; j < arr.length - 1 - i; j++) {
console.log(1)
// console.log(i, j)
if (arr[j] < arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
/**
* 0 0
* 0 1
* 0 2
* 0 3
* 0 4
* 1 0
* 1 1
* 1 2
* 1 3
* 2 0
* 2 1
* 2 2
* 3 0
* 3 1
* 4 0
*/
实现2
/**
* 前面是从第一个到最后一个往后冒泡
* 也可以从最后一个到第一个往前冒泡
* 需要固定循环(arr.length)*(arr.length)次数
*/
function bubbleSort3(arr) {
for (var i = arr.length - 1; i >= 0; i--) {
for (var j = 0; j < arr.length; j++) {
console.log(1)
// console.log(i,j)
if (arr[j] < arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
优化1
// 优化里层越界问题
// 需要固定循环(arr.length)*(arr.length-1)次数
function bubbleSort4(arr) {
for (var i = arr.length - 1; i >= 0; i--) {
for (var j = 0; j < arr.length - 1; j++) {
console.log(1)
// console.log(i,j)
if (arr[j] < arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
优化2
// 优化里层循环
// 需要固定循环((arr.length)*(arr.length))/2次数
function bubbleSort5(arr) {
for (var i = arr.length - 1; i >= 0; i--) {
// 互换过的下次就不互换,即每次内层循环次数随着外层越来越小
// 第一轮内层循环互换arr.length - 1 - 0次,即5次
// 第二轮内层循环互换arr.length - 1 - 1次,即4次
// 第三轮内层循环互换arr.length - 1 - 2次,即3次
// 第四轮内层循环互换arr.length - 1 - 3次,即2次
// 第五轮内层循环互换arr.length - 1 - 5次,即1次
// 第六轮内层循环互换arr.length - 1 - 6次,即0次
for (var j = 0; j < i; j++) {
// console.log(1)
console.log(i, j)
if (arr[j] < arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
/**
* 5 0
* 5 1
* 5 2
* 5 3
* 5 4
* 4 0
* 4 1
* 4 2
* 4 3
* 3 0
* 3 1
* 3 2
* 2 0
* 2 1
* 1 0
*/
上一篇: 气泡排序的 C++ 实现
下一篇: 冒牌排序法详解
推荐阅读
-
正负偏差变量 即 d2+、d2- 分别表示决策值中超出和未达到目标值的部分。而 di+、di- 均大于 0 刚性约束和目标约束(柔性目标约束有偏差) 在多目标规划中,>=/<= 在刚性约束中保持不变。当需要将约束条件转换为柔性约束条件时,需要将 >=/<= 更改为 =(因为已经有 d2+、d2- 用来表示正负偏差),并附加上 (+dii-di+) 注意这里是 +di、-di+!之所以是 +di,-di+,是因为需要将目标还原为最接近的原始刚性约束条件 优先级因素和权重因素 对多个目标进行优先排序和优先排序 目标规划的目标函数 是所有偏差变量的加权和。值得注意的是,这个加权和都取最小值。而 di+ 和 dii- 并不一定要出现在每个不同的需求层次中。具体分析需要具体问题具体分析 下面是一个例子: 题目中说设备 B 既要求充分利用,又要求尽可能不加班,那么列出的时间计量表达式即为:min z = P3 (d3- + d3 +) 使用 + 而不是 -d3 + 的原因是:正负偏差不可能同时存在,必须有 di+di=0 (因为判定值不可能同时大于目标值和小于目标值),而前面是 min,所以只要取 + 并让 di+ 和 dii- 都为正值即可。因此,得出以下规则: 最后,给出示例和相应的解法: 问题:某企业生产 A 和 B 两种产品,需要使用 A、B、C 三种设备。下表显示了与工时和设备使用限制有关的产品利润率。问该企业应如何组织生产以实现下列目标? (1) 力争利润目标不低于 1 500 美元; (2) 考虑到市场需求,A、B 两种产品的生产比例应尽量保持在 1:2; (3)设备 A 是贵重设备,严禁超时使用; (4)设备 C 可以适当加班,但要控制;设备 B 要求充分利用,但尽量不加班。 从重要性来看,设备 B 的重要性是设备 C 的三倍。 建立相应的目标规划模型并求解。 解:设企业生产 A、B 两种产品的件数分别为 x1、x2,并建立相应的目标计划模型: 以下为顺序求解法,利用 LINGO 求解: 1 级目标: 模型。 设置。 variable/1..2/:x;! s_con_num/1...4/:g,dplus,dminus;!所需软约束数量(g=dplus=dminus 数量)及相关参数; s_con(s_con_num);! s_con(s_con_num,variable):c;!软约束系数; 结束集 数据。 g=1500 0 16 15. c=200 300 2 -1 4 0 0 5; 结束数据 min=dminus(1);!第一个目标函数;!对应于 min=z 的第一小部分;! 2*x(1)+2*x(2)<12;!硬约束 @for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); !使用设置完成的数据构建软约束表达式; ! !软约束表达式 @for(variable:@gin(x)); !将变量约束为整数; ! 结束 此时,第一级目标的最优值为 0,第一级偏差为 0: 第二级目标: !求 dminus(1)=0,然后求解第二级目标。 模型。 设置。 变量/1..2/:x;!设置:变量/1..2/:x; ! s_con_num/1...4/:g,dplus,dminus;!软约束数量及相关参数; s_con(s_con_num(s_con_num));! s_con(s_con_num,variable):c;! 软约束系数; s_con(s_con_num,variable):c;! 结束集 数据。 g=1500 0 16 15; c=200 300 2 -1 4 0 0 5; 结束数据 min=dminus(2)+dplus(2);!第二个目标函数 2*x(1)+2*x(2)<12;!硬约束 @for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); ! 软约束表达式;! dminus(1)=0; !第一个目标结果 @for(variable:@gin(x)); ! 结束 此时,第二个目标的最优值为 0,偏差为 0: 第三目标 !求 dminus(2)=0,然后求解第三个目标。 模型。 设置。 变量/1..2/:x;!设置:变量/1..2/:x; ! s_con_num/1...4/:g,dplus,dminus;!软约束数量及相关参数; s_con(s_con_num(s_con_num));! s_con(s_con_num,variable):c;! 软约束系数; s_con(s_con_num,variable):c;! 结束集 数据。 g=1500 0 16 15; c=200 300 2 -1 4 0 0 5; 结束数据 min=3*dminus(3)+3*dplus(3)+dminus(4);!第三个目标函数。 2*x(1)+2*x(2)<12;!硬约束 @for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); ! 软约束表达式;! dminus(1)=0; !第一个目标约束条件; ! dminus(2)+dplus(2)=0; !第二个目标约束条件 @for(variable:@gin(x));! 结束 最终结果为 x1=2,x2=4,dplus(1)=100,最优利润为
-
气泡排序和一些优化
-
气泡排序、两种实现方式和优化
-
经典气泡排序和优化气泡排序法
-
气泡排序和优化详解
-
图解气泡排序和算法优化(Java 实现)
-
气泡排序:理解、实施和性能优化
-
排序算法:气泡排序(改进版)的思路分析和代码实现
-
[排序算法] 气泡排序(改进版)的思路分析和代码实现细节 - 二次行程排序:
-
排序算法 - 气泡排序的原理和代码实现