上一篇文章讲了冒泡排序、选择排序、插入排序。
这篇文章来讲归并排序和快速排序。
1、归并排序
归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
下面来看代码实现:
Array.prototype.mergeSort = function() {
const rec = (arr) => {
if (arr.length === 1) { return arr; }
const mid = Math.floor(arr.length / 2);
const left = arr.slice(0, mid);
const right = arr.slice(mid, arr.length);
const orderLeft = rec(left);
const orderRight = rec(right);
const res = [];
while(orderLeft.length || orderRight.length) {
if (orderLeft.length && orderRight.length) {
res.push(orderLeft[0] < orderRight[0] ? orderLeft.shift() : orderRight.shift())
} else if (orderLeft.length) {
res.push(orderLeft.shift());
} else if (orderRight.length) {
res.push(orderRight.shift());
}
}
return res;
};
const res = rec(this);
res.forEach((n, i) => {
this[i] = n;
})
return res;
}
let arr = [5, 4, 3, 2, 1];
console.log(arr.mergeSort()); // [ 1, 2, 3, 4, 5 ]
时间复杂度为:O(nlogn)
2、快速排序
快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
Array.prototype.quickSort = function() {
const rec = (arr) => {
if (arr.length === 0) {return arr;} // 不加这一行代码的话最大调用栈会溢出
if (arr.length === 1) { return arr; }
const mid = arr[0];
const left = [];
const right = [];
for (let i = 1; i < arr.length; i++) {
if (arr[i] < mid) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return [...rec(left), mid, ...rec(right)];
}
const res = rec(this);
res.forEach((n, i) => {
this[i] = n;
})
return res;
}
let arr = [5, 4, 3, 2, 1]; // [ 1, 2, 3, 4, 5 ]
console.log(arr.quickSort());
时间复杂度为:O(nlogn)
至此,用JavaScript写成的五大排序算法就已经全部完成了,分别是冒泡排序、选择排序、插入排序、归并排序、快速排序。
如果你有哪里不懂的话,欢迎留言或者私信问我。