排序算法集合

391 阅读3分钟

一. 冒泡排序

// 思路:比较相邻的元素,每次比较都会生成最大或者最小值放在最后,所以每轮比较次数会递减
function sort(arr) {
    for (let i = 0; i < arr.length - 1; i += 1) { // 一共比较length - 1轮
        for (let j =0; j < arr.length - 1 - i; j += 1) { // 每轮比较的次数(递减)
            if (arr[j] > arr[j + 1]) {
                [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
            }
        }
    }
}

二. 快排

// 思路:双指针 + 递归分治。每次比较都能找到基值的位置,然后递归比较基值左右的部分
function sort(arr, start, end) {
    if (start >= end) return;
    let left = start, right = end;
    const basic = arr[start]; // 基值
    while(left < right) {
        while(left < right && arr[right] >= basic ) right--; // 右指针比较直到找到比基值小的值则暂停
        while(left < right && arr[left] <= basic) left++; // 左指针比较直到找到比基值大的值则暂停
        [arr[left], arr[right]] = [arr[right], arr[left]] // 交换左右指针所指的值
    }
    [arr[start], arr[left]] = [arr[left], arr[start]];
    // 左右分治
    sort(arr, start, left - 1);
    sort(arr, left + 1, end);
}

三. 选择排序

// 思路:和冒泡有点相似,每轮比较得出该轮的最小值,然后把最小值放在最前面;然后比较剩下的值,得出次小值。
function sort(arr) {
    var l = arr.length;
    for (let i = 0; i < l; i += 1) {
        var c = arr.slice(i, l); // 每次截取剩下的元素进行比较
	var min = Math.min(...c); // 获取到当前被比较的元素的最小值
	var index = arr.indexOf(min); // 获取到最小值所在的索引位置
	arr.splice(index, 1); // 将最小值从当前元素集中剔除
	arr.splice(i, 0, min) // 将最小值移动到前面位置
    }
	return arr;
}

四. 插入排序

// 思路: 从数组的第二项开始,将元素和该元素之前的元素级比较,如果比前面的元素小,则继续往前比较,直至
        比较到第一个位置或者出现该元素大于前面的元素为止。将该元素插到这个位置。
function sort(arr) {
    for (let i = 1; i < arr.length; i += 1) {
        let j = i; // 记录当前元素前面有几个元素
        const temp = arr[i]
        while(j > 0 && temp < arr[j - 1]) { // 将该元素和之前的元素比较,直到找到大于前面元素的位置
            j--;
        }
        if (j != i) {
           arr.splice(i, 1);
           arr.splice(j, 0, temp); // 将temp移动到j的位置
        }
    }
    return arr;
}

五. 希尔排序

思路: 。。。。。。
function sort(arr) {
	for (let z = Math.floor(arr.length / 2); z >= 1; z = Math.floor(z / 2)) {
		for (let i = 0; i < arr.length && arr[i + z]; i += 1) {
			if (arr[i] > arr[i + z]) {
				[arr[i], arr[i + z]] = [arr[i + z], arr[i]];
			}
		}
	}
	return arr;
}

六. 计数排序

思路: 创建另一个数组来映射来源数组,映射规则为数组的索引对应来源数组的值,数组索引对应的值映射来源数组值出现的次数。
       举个例子:
const originArr = [4,3,2,1,3,2]; => const mapArr = [0, 1, 2, 2, 1]; 
实现:
function sort(arr) {
	const max = Math.max(...arr); // 创建一个长度为源数组最大值的数组
	const arr2 = new Array(max + 1);
	arr2.fill(0, 0); // 为映射数组初始化值
	for (let i = 0; i < arr.length; i += 1) {
		const v = arr[i];
		arr2[v]++;
	}
	const results = [];
	let index = 0;
	for (let j = 0; j < arr2.length; j += 1) {
		while(arr2[j]) {
			results[index++] = j;
			arr2[j]--;
		}
	}
	return results;
}