说实话,在写项目的时候,需要自己手写一个排序的情况可能性还真的小。
那为啥突然想写这样一篇文章,之前都是用的 C/C++ 来实现这些排序,这次用下 JS 来实现
冒泡排序
思路就是比较相邻的两个元素,是大于还是小于,取决于你是想要升序还是降序排序
平均复杂度O(n^2),最好O(n),最坏O(n^2),是稳定排序
function bubbleSort(arr) {
const len = arr.length;
for(let i = 0; i < len - 1; i++) {
for(let j = 0; j < len - 1 - i; j++) {
if(arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
选择排序
每次遍历都找出当前下标后面的最大(最小)值的下标,然后当前下标交换
复杂度都是O(n^2),而且是不稳定排序
function selectionSort(arr) {
const len = arr.length;
let index;
for (let i = 0; i < len; i++) {
index = i;
for (let j = i + 1; j < len; j++) {
arr[j] < arr[index] ? index = j : ""
}
[arr[index], arr[i]] = [arr[i], arr[index]]
}
return arr
}
插入排序
分两组:左边有序,右边无序。在右边每一个都会跟左边倒序比较,找到比自身大的(小的)就插入
平均复杂度O(n^2),最好O(n),最快O(n^2),和冒泡一样,这个是稳定排序
function insertSort(arr) {
const len = arr.length;
let tempIndex, temp;
for (let i = 1; i < len; i++) {
tempIndex = i - 1;
temp = arr[i];
while (tempIndex >= 0 && arr[tempIndex] > temp) {
arr[tempIndex + 1] = arr[tempIndex];
tempIndex--;
}
arr[tempIndex + 1] = temp;
}
return arr;
}
希尔排序
是插入排序的一种更高效的版本
平均复杂度是O(n logn),是不稳定排序
function shellSort(arr) {
const len = arr.length;
let temp, gap = 1;
while (gap < len / 3) {
gap = gap * 3 + 1;
}
for (; gap > 0; gap = Math.floor(gap / 3)) {
for (let i = gap; i < len; i++) {
temp = arr[i];
let j
for (j = i - gap; j > 0 && arr[j] > temp; j -= gap) {
arr[j + gap] = arr[j];
}
arr[j + gap] = temp;
}
}
return arr;
}
归并排序
归并排序是采用的分治的思想来实现的
复杂度都是O(n logn),而且它是稳定排序
function mergeSort(arr) {
const len = arr.length;
if (len < 2) {
return arr;
}
const middle = Math.floor(len / 2),
left = arr.slice(0, middle),
right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right) {
let result = [];
while (left.length && right.length) {
let t = left[0] <= right[0] ? left.shift() : right.shift();
result.push(t);
}
left.length && (result = result.concat(left));
right.length && (result = result.concat(right));
return result;
}
快速排序
在一个区间中取一个基准,让这个基准的左边都比这个小,右边都比这个大;再分别对区间进行排序
平均复杂度是O(n logn),最坏的情况时O(n^2),是不稳定排序
function quickSort(arr, left, right) {
let len = arr.length, partitionIndex;
left = typeof left != "number" ? 0 : left,
right = typeof right != "number" ? len - 1 : right;
if (left < right) {
partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex - 1);
quickSort(arr, partitionIndex + 1, right);
}
return arr;
}
function partition(arr, left, right) {
let flag = left,
index = flag + 1;
for (let i = index; i <= right; i++) {
if(arr[i] < arr[flag]) {
[arr[index], arr[i]] = [arr[i], arr[index]]
index++;
}
}
[arr[index - 1], arr[flag]] = [arr[flag], arr[index - 1]]
return index - 1
}
堆排序
复杂度都是O(n logn),是不稳定排序
let len;
function buildMaxHeap(arr) {
len = arr.length;
for (let i = Math.floor(len / 2); i >= 0; i--) {
heapify(arr, i);
}
}
function heapify(arr, i) {
let left = i * 2 + 1,
right = i * 2 + 2;
let largest = i;
if (left < len && arr[left] > arr[largest]) {
largest = left;
}
if (right < len && arr[right] > arr[largest]) {
largest = right;
}
if (largest !== i) {
[arr[i], arr[largest]] = [arr[largest], arr[i]];
heapify(arr, largest);
}
}
function heapSort(arr) {
buildMaxHeap(arr);
for (let i = arr.length - 1; i > 0; i--) {
[arr[0], arr[i]] = [arr[i], arr[0]];
len--;
heapify(arr, 0)
}
return arr;
}
又回顾了一遍