前言
本文将介绍几种常见的排序算法,包括改进后的冒泡排序,插入排序,并归排序,选择排序
改进后的冒泡排序
思路
方法一:设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可
方法二:进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) , 从而使排序趟数几乎减少了一半。
代码
// 改进后的冒泡排序
//方法一
function bubbleSort1(arr) {
var i = arr.length - 1;
while (i > 0) {
var pos = 0;
for (let j = 0; j < i - pos; j++) {
if (arr[j] > arr[j + 1]) {
pos = j;
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
i = pos;
}
}
return arr;
}
// 改进的冒泡排序
//方法二
function bubbleSort2(arr) {
let low = 0;
let high = arr.length - 1;
while (low < high) {
for (let i = 0; i < high; i++) {
if (arr[i] > arr[i + 1]) {
let temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
high--;
for (let j = high; j > low; j--) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
low++;
}
return arr;
}
插入排序
思路
<1>.从第一个元素开始,该元素可以认为已经被排序;
<2>.取出下一个元素,在已经排序的元素序列中从后向前扫描;
<3>.如果该元素(已排序)大于新元素,将该元素移到下一位置;
<4>.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
<5>.将新元素插入到该位置后;
<6>.重复步骤2~5。
代码
function binaryInsertSort(arr) {
for (let i = 1; i < arr.length; i++) {
let left = 0;
let right = i - 1;
let key = arr[i];
//使用二分法找到已排序的数组中大于key的项
while (left <= right) {
let middle = parseInt((left + right) / 2);
if (key < arr[middle]) {
right = middle - 1;
} else {
left = middle + 1; //最后在已排序的数组中大于key的value的索引是left。
}
}
for (let j = i - 1; j >= left; j--) {
arr[j + 1] = arr[j];
}
arr[left] = key
}
return arr;
}
选择排序
思路
每次循环选取一个最小的数字放到前面的有序序列中。
代码
function selectionSort(arr) {
for(let i = 0;i < arr.length-1; i++) {
let minIndex =i;
for(let j = i + 1;j < arr.length;j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
[arr[minIndex],arr[i]] = [arr[i],arr[minIndex]]
}
}
并归排序
思路
并归排序,时间复杂度:O(nlogn)
分割:
将数组从中点进行分割,分为左、右两个数组
递归分割左、右数组,直到数组长度小于2
归并:
如果需要合并,那么左右两数组已经有序了。
创建一个临时存储数组temp,比较两数组第一个元素,将较小的元素加入临时数组
若左右数组有一个为空,那么此时另一个数组一定大于temp中的所有元素,直接将其所有元素加入temp
代码
function mergeSort(array) {
if (array.length < 2) {
return array;
}
const mid = Math.floor(array.length / 2);
const front = array.slice(0, mid);
const end = array.slice(mid);
return merge(mergeSort(front), mergeSort(end));
}
function merge(left, right) {
const result = [];
while(i < left.length && j < right.length) {
if (left[i] <= right[j]) {
result.push(left[i++])
} else {
result.push(right[j++])
}
}
//遍历结束后,左右两个可能会有剩余,就把剩余的数组添加到result的后面。
if (i < left.length) {
result.push(...left.slice(i))
} else {
result.push(...right.slice(j))
}
return result
}