JS的排序分类
数据结构算法中排序有很多种,常见的、不常见的,至少包含十种以上。根据它们的特性,可以大致分为两种类型:比较类排序和非比较类排序。
-
比较类排序: 通过比较来决定元素间的相对次序,其时间复杂度不能突破 O(nlogn),因此也称为非线性时间比较类排序,在这我们也是主讲比较类排序。大致可以分为下面四大类:
-
交换排序
- 冒泡排序
- 快速排序
-
插入排序
-
选择排序
- 普通选择排序
- 堆排序
-
归并排序
-
-
非比较类排序 :不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。大致包含下面几大类:
- 桶排序
- 基数排序
- 计数排序
属性一览
| 排序算法 | 时间复杂度 | 空间复杂度 | 稳定性 |
|---|---|---|---|
| 冒泡排序 | O(n²) | O(1) | 稳定 |
| 快速排序 | O(n*logn) | O(n*logn) | 不稳定 |
| 插入排序 | O(n²) | O(1) | 稳定 |
| 选择排序 | O(n²) | O(1) | 不稳定 |
| 堆排序 | O(n*logn) | O(1) | 不稳定 |
| 归并排序 | O(n*logn) | O(N) | 稳定 |
代码实现
1. 冒泡排序
冒泡和选择作为学习排序最基础的排序,在这我就直接上代码了
- 代码
// 冒泡排序
var a = [1, 3, 6, 3, 23, 76, 1, 34, 222, 6, 456, 221];
function bubbleSort(arr) {
const len = arr.length;
// 边界,数组长度小于2
if (len < 2) {
return arr;
}
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++){
if (arr[i] > arr[j]) {
let num = arr[i];
arr[i] = arr[j];
arr[j] = num;
}
}
}
return arr;
}
console.log(bubbleSort(a));
2. 选择排序
- 代码
// 选择排序
var a = [1, 3, 6, 3, 23, 76, 1, 34, 222, 6, 456, 221];
function selectSort(array) {
const len = array.length
let temp
let minIndex
for (let i = 0; i < len - 1; i++) {
minIndex = i
for (let j = i + 1; j < len; j++) {
if (array[j] <= array[minIndex]) {
minIndex = j
}
}
temp = array[i]
array[i] = array[minIndex]
array[minIndex] = temp
}
return array
}
console.log(selectSort(a));
3. 快速排序 快排前期单独写过文章,里面每一步都有进行讲解5分钟速通快排
- 思想
- 从数列中挑出一个元素,称为 "基准"(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
- 代码
// 快排
var a = [1, 3, 6, 3, 23, 76, 1, 34, 222, 6, 456, 221];
function quickSort(nums) {
if (nums.length < 2) {
return nums;
}
let num = nums.splice(0,1);
let left = [];
let right = [];
nums.forEach(element => {
if (element > num) {
right.push(element);
} else {
left.push(element);
}
});
return quickSort(left).concat(num,quickSort(right));
}
console.log(quickSort(a));
4. 插入排序
- 思想:
- 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列
- 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
- 代码
// 插入排序
var a = [1, 3, 6, 3, 23, 76, 1, 34, 222, 6, 456, 221];
function insertSort(arr) {
let fast;
let slow;
for (let i = 0; i < arr.length; i++) {
fast = arr[i];
slow = i - 1;
while (slow > 0 && arr[slow] > fast) {
arr[slow + 1] = arr[slow];
slow--;
}
arr[slow+1] = fast;
}
return arr;
}
console.log(insertSort(a));
5. 归并排序
- 思想
- 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
- 设定两个指针,最初位置分别为两个已经排序序列的起始位置
- 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
- 重复步骤 3 直到某一指针达到序列尾
- 将另一序列剩下的所有元素直接复制到合并序列尾
// 归并排序
var a = [1, 3, 6, 3, 23, 76, 1, 34, 222, 6, 456, 221];
function mergeSort() {
const merge = (left, right)=>{
const result = [];
let l = 0;
let r = 0;
while (l < left.length && r < right.length) {
if (left[l] < right[r]) {
result.push(left[l++]);
} else {
result.push(right[r++])
}
}
while (l < left.length) {
result.push(left[l++])
}
while (r < right.length) {
result.push(right[r++])
}
return result;
}
const mergesort = (array) => {
if (array.length < 2) {
return array;
}
const middle = Math.floor(array.length / 2);
const left = array.slice(0, middle);
const right = array.slice(middle, array.length);
return merge(mergesort(left), mergesort(right));
}
return mergesort(a);
}
console.log(mergeSort(a));
6. 堆排序
堆排序个人认为是入门门槛最高的一种算法,理解起来也是有一定难度的,大家可以多花点时间先将图片看一看,理解每一步的原理,然后可以结合代码试试自己手写实现
-
思想
- 创建一个堆 H[0……n-1]
- 把堆首(最大值)和堆尾互换
- 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置
- 重复步骤 2,直到堆的尺寸为 1
-
代码
// 堆排序
var a = [1, 3, 6, 3, 23, 76, 1, 34, 222, 6, 456, 221];
function heap_sort(arr) {
var len = arr.length
var k = 0
function swap(i, j) {
var temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
function max_heapify(start, end) {
var dad = start
var son = dad * 2 + 1
if (son >= end) return
if (son + 1 < end && arr[son] < arr[son + 1]) {
son++
}
if (arr[dad] <= arr[son]) {
swap(dad, son)
max_heapify(son, end)
}
}
for (var i = Math.floor(len / 2) - 1; i >= 0; i--) {
max_heapify(i, len)
}
for (var j = len - 1; j > k; j--) {
swap(0, j)
max_heapify(0, j)
}
return arr
}
heap_sort(a); // [1, 1, 3, 3, 6, 6, 23, 34, 76, 221, 222, 456]
总结
排序算法其实远远不止这几种,,引申开了还有希尔排序等等许许多多,想学习更多在这给大家推荐菜鸟,里面十大经典算法都有实现和图解,我本人也是在上面自学的算法,在这进行一下复习写文章。
我是江河,前端实习生一枚,目前正在准备春招实习,欢迎各位大佬滴滴,文章如有不正之处敬请斧正!