JavaScript数据结构与算法:冒泡排序及其优化方法
基本概念
冒泡排序是一种基本的排序算法。基本思想是通过不断比较相邻元素并在必要时交换它们,将最大(或最小)元素“冒险”到序列的一端。
排序步骤
首先来体验一下冒泡排序的步骤
我们以集合[5,3,8,4,6]为例。冒泡排序的步骤如下:
- 第一轮排序:
比较相邻元素。当我们首先比较5和3时,5大于3,我们交换它们,矩阵变成[3,5,8,4,6];然后比较5和8,5小于8,不需要交换,再比较8和4,8大于4,交换,数组变成[3, 5, 4, 8, 6] ;最后比较8和6,8大于6,交换,矩阵变为[3,5,4,6,8]。就这样,经过第一轮的比较,数量最高的8名排在了最后。
- 第二轮排序:
再次从前到后比较相邻元素。这次由于8已经是末尾最大的元素,所以不再纳入比较。首先比较3和5,3小于5,不需要交换;然后比较5和4,5大于4,交换,字符串变成[3,4,5,6,8];然后比较5和5 6.5小于6不需要交换。这样,第二轮排序就完成了,第二大元素6也放到了它应该在的地方。
- 下一轮排序:
如此重复,每轮比较的元素对数量比上一轮少一个。直到全部排序完毕。
最后,字符串 [5, 3, 8, 4, 6] 被排序为 [3, 4, 5, 6, 8]。
冒泡排序实现
let array = [5, 3, 8, 4, 6];
for(let i = 0; i < array.length; i++) {
for(let j = 0; j < array.length - i - 1; j++) {
if(array[j] > array[j + 1]) {
// 交换元素
let temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
console.log(array); // 输出: [3,
4, 5, 6, 8]该算法的时间复杂度为O(n^2),因此在处理大量数据时可能效率较低。
优化策略
替换标志
如果过渡过程中没有发生替换,则说明序列已经没问题,无需进一步排序。可以通过设置标志来优化算法。如果在给定的转换期间没有发生交换,则排序直接结束。
这种优化可以极大地提高已经部分排序的序列的性能。
let array = [5, 3, 8, 4, 6];
let swapped = true;
while(swapped) {
swapped = false;
for(let i = 0; i < array.length - 1; i++) {
if(array[i] > array[i + 1]) {
let temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
swapped = true;
}
}
}
console.log(array); // 输出: [3, 4, 5, 6, 8]双向冒泡排序
一次遍历只能保证最大(或最小)的数移动到序列的一端。双向冒泡排序中,一次遍历涉及两个过程,一个端到端,一个端到端开始,这样可以保证遍历一遍后最大和最小的数都移动到正确的位置。
let array = [5, 3, 8, 4, 6];
let swapped;
let start = 0;
let end = array.length - 1;
while(start < end) {
for(let i = start; i < end; i++) {
if(array[i] > array[i + 1]) {
let temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
swapped = i;
}
}
end = swapped;
for(let i = end; i > start; i--) {
if(array[i] < array[i - 1]) {
let temp = array[i];
array[i] = array[i - 1];
array[i - 1] = temp;
swapped = i;
}
}
start = swapped;
}
console.log(array); // 输出: [3, 4, 5, 6, 8]记录最后一次交换的位置
在实际的数据序列中,末尾通常会有多个有序序列,这样我们就可以记住最后一次交换发生的位置,并在下次与该位置进行比较。
let array = [5, 3, 8, 4, 6];
let lastExchangeIndex = 0;
let sortBorder = array.length - 1;
for(let i =
0; i < array.length - 1; i++) {
let isSorted = true;
for(let j = 0; j < sortBorder; j++) {
if(array[j] > array[j + 1]) {
let temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
isSorted = false;
lastExchangeIndex = j;
}
}
sortBorder = lastExchangeIndex;
if(isSorted) {
break;
}
}
console.log(array); // 输出: [3, 4, 5, 6, 8] 版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网