数组的排序
在很多应用场景中会用到数据的排序,下面简单介绍几种排序方法
交换方法es6写法
function swap(array, index1, index2) {
[array[index1], array[index2]] = [array[index2], array[index1]];
return array;
}
1.冒泡排序:
比较任何两个相邻的项,如果第一个比第二个大,则交换它们。元素项向上移动至正确的顺序,就好像气泡升至表面一样,冒泡排序因此得名
时间复杂度:搜索n平方次 O(nˇ2)
function bubbleSort(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr.length - 1-i; j++) { // 第一轮排序已经把最大值放在最后面,第二轮排序不需要比较最后一位
if (arr[j] > arr[j + 1]) {
arr = swap(arr, j, j + 1);
}
}
}
return arr;
}
2.插入排序:
插入排序每次排一个数组项,以此方式构建最后的排序数组。 假定第一项已经排序了,接着, 它和第二项进行比较,第二项是应该待在原位还是插到第一项之前呢? 这样,头两项就已正确排 序,接着和第三项比较(它是该插入到第一、第二还是第三的位置呢?以此类推。
时间复杂度:搜索n平方次 O(nˇ2)
function insertSort(array) {
console.time("插入排序")
var length = array.length;
var j;
var temp;
for (var i = 1; i < length; i++) {
j = i;
temp = array[i];
while (j > 0 && array[j - 1] > temp) {
array[j] = array[j - 1];
j--;
}
array[j] = temp;
}
console.timeEnd("插入排序")
return array;
}
3.选择排序:
选择排序算法是一种原址比较排序算法。选择排序大致的思路是找到数据结构中的最小值并将其放置在第一位,接着找到第二小的值并将其放在第二位,以此类推。
时间复杂度:搜索n平方次 O(nˇ2)
function selectSort(array) {
console.time("选择排序")
var length = array.length;
var indexMin;
for (var i = 0; i < length - 1; i++) {
indexMin = i;
for (var j = i; j < length; j++) {
if (array[indexMin] > array[j]) {
indexMin = j;
}
}
if (i !== indexMin) {
array = swap(array, i, indexMin);
}
}
console.timeEnd("选择排序")
return array;
}
4.快速排序:
快速排序的思想:数组中指定一个元素作为标尺,比它大的放到该元素后面,比它小的放到该元素前面,如此重复直至全部正序排列。
快速排序分三步:
选基准:在数据结构中选择一个元素作为基准(pivot)
划分区:参照基准元素值的大小,划分无序区,所有小于基准元素的数据放入一个区间,所有大于基准元素的数据放入另一区间,分区操作结束后,基准元素所处的位置就是最终排序后它应该所处的位置
递归:对初次划分出来的两个无序区间,递归调用第 1步和第 2步的算法,直到所有无序区间都只剩下一个元素为止。
时间复杂度:每次都要进行把数组分两半,二分查找的时间复杂度为 O(log n) ,比较的次数为n次
// 普遍实现快速排序的方法
function quickSort(arr) {
if (arr.length <= 1) {
return arr
}
var pivotIndex = Math.floor(arr.length / 2); // 指定分区基点
var pivot = arr.splice(pivotIndex,1)[0]; // 这里需要改变原数组提出基元素 作为递归的关闭条件
var left = [];
let right = [];
for (var i=0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot],quickSort(right)); // 合并每次分完的数组
}
5.归并排序:
归并排序是一种分治算法。
其思想是将原始数组切分成较小的数组,直到每个小数组只有一 个位置,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。
时间复杂度:
function mergeSort(array) {
console.time("归并排序");
array = mergeSortRec(array);
console.timeEnd("归并排序");
return array;
}
// 数组分组
function mergeSortRec(array) {
var length = array.length;
if (length === 1) {
return array;
}
var indexMid = Math.floor(length / 2);
var left = array.slice(0, indexMid);
var right = array.slice(indexMid, length);
return merge(mergeSortRec(left), mergeSortRec(right));
}
// 归并
function merge(left, right) {
var result = [];
var il = 0,
ir = 0;
while (il < left.length && ir < right.length) {
if (left[il] < right[ir]) {
result.push(left[il++]);
} else {
result.push(right[ir++]);
}
}
while (il < left.length) {
result.push(left[il++]);
}
while (ir < right.length) {
result.push(right[ir++]);
}
return result;
}