阅读 345

JS数据结构与算法之排序查找算法

前言

掌握多种常用算法可以提升我们自身的内力,锻炼我们的逻辑思维。

交换函数

function swap(array, a, b) {
    [array[a], array[b]] = [array[b], array[a]];
}
复制代码

冒泡排序

//冒泡排序
function bubbleSort(array) {
    const { length } = array;
    for (let i = 0; i < length; i++) {
        //-i的目的是随着趟数的增加,就不需要再对最后排好序的元素进行比较了
        for (let j = 0; j < length - 1 - i; j++) {
            if (array[j] > array[j + 1]) {
            	swap(array, j, j + 1);
            }
        }
    }
    return array;
}
复制代码

选择排序

原地排序算法。选择排序大致的思路是找到数据结构中的最小值并 将其放置在第一位,接着找到第二小的值并将其放在第二位,以此类推

function selectionSort(array) {
    const length = array.length;
    let indexMin;
    for (let i = 0; i < length - 1; i++) {
    indexMin = i;
    for (let j = i; j < length; j++) {
        if (array[indexMin] > array[j]) {
            indexMin = j;
        }
    }
    if (i !== indexMin) {
    	swap(array, i, indexMin);
    }
  }
  return array;
}
复制代码

插入排序

插入排序每次排一个数组项,以此方式构建最后的排序数组。假定第一项已经排序了。

接着,它和第二项进行比较:第二项是应该待在原位还是插到第一项之前呢?这样,头两项就已正确排序,接着和第三项比较(它是该插入到第一、第二还是第三的位置呢),以此类推。。

排序小型数组时,此算法比选择排序和冒泡排序性能要好。

function insertionSort(array) {
    const length = array.length;
    let temp;
    for (let i = 1; i < length; i++) {
    let j = i;
    temp = array[i];
    while (j > 0 && array[j - 1] > temp) {
    	array[j] = array[j - 1];
    	j--;
    }
        array[j] = temp;
   }
    return array;
}
复制代码

希尔排序

希尔排序是第一个突破O(n²)的算法,是基于插入排序的算法,通常情况都是好于O(n²)

function shellSort(array) {
    const length = array.length;
    //间隔
    let gap = (length / 2) | 0;
    while (gap >= 1) {
    	//以gap作为间隔分组,然后插入排序;
    	for (let i = gap; i < length; i++) {
            let temp = array[i];
            let j = i;
            while (j > gap - 1 && array[j - gap] > temp) {
            	array[j] = array[j - gap];
            	j -= gap;
            }
            array[j] = temp;
    	}
    	gap = Math.floor(gap / 2);
    }
}
复制代码

归并排序

归并排序是第一个可以实际使用的排序算法 归并排序性能不错,其复杂度为 O(nlog(n))

例如,Mozilla Firefox使用了归并排序作为 Array.prototype.sort 的实现

归并排序是分治法,递归的,我们要将算法分成两个函数,第一个函数是将大数组切分为多个小数组并调用排序的辅助函数

function mergeSort(array) {
	//归并排序将一个大数组转化为多个小数组直到其中只有一个项。由于算法是递归的,我们需要一个停止条件,在这里此条件是判断数组的长度是否为 1
	if (array.length > 1) {
            const { length } = array;
            const middle = Math.floor(length / 2);
            const left = mergeSort(array.slice(0, middle));
            const right = mergeSort(array.slice(middle, length));
            array = merge(left, right);
	}
	return array;
}
function merge(left, right) {
	let i = 0;
	let j = 0;
	const result = [];
	while (i < left.length && j < right.length) {
            result.push(left[i] > right[j] ? left[i++] : right[j++]);
	}
	return result.concat(i < left.length ? left.slice(i) : right.slice(j));
}
复制代码

二分查找

这个算法要求是被搜索的数据结构是已排序的 过程是:

1.选择数组的中间值

2.如果选中值是待搜索值,那么直接返回,算法执行完毕

3.如果待搜索值比选中值要小,则返回步骤一并在选中值左边的子数组中寻找(较小)

4.如果待搜索值比选中值要大,则返回步骤一并在选中值右边的子数组中寻找(较大)

function binarySearch(array, target) {
	let low = 0;
	let high = array.length - 1;
	while (low <= high) {
            const mid = Math.floor((low + high) / 2);
            const middleValue = array[mid];
            if (middleValue > target) {
            	high = mid - 1;
            } else if (middleValue < target) {
            	low = mid + 1;
            } else {
            	return mid;
            }
	}
	return -1;
}

复制代码

结语

以上就是常用的排序方法了