前言
JS中的排序
const arr = [1,22,3,11];// 先转成字符串,按照 ASCII 的码进行排序arr.sort(); // [1,11,22,3]// 升序排序arr.sort((a, b)=> a - b)// 降序排序arr.sort((a, b)=> b - a)// 反序 arr.reverse()// 返回其他值,不排序arr.sort(()=> -1)// 自定义排序arr.sort((a, b)=>{// 升序if(a - b > 0) return 1;// 降序if(a - b < 0) return -1;return 0})// 非 ASCII 排序arr.sort((a, b)=>{return a.localeCompare(b);})
快速排序
平均时间复杂度是nlogn 1、挑选一个基准值 2、分割:比基准值小的放左边,比基准值大的放右边,这个过程基准值的排序就完成了 3、递归排列左右子序列
function sort(arr=[]) {if (!Array.isArray(arr) || arr.length <= 1) return arr;const left = [], right = [];const midIndex = Math.floor(arr.length / 2);const mid = arr[midIndex];let midCount = 0;for (let i = 0; i < arr.length; i++) {const item = arr[i];if (item < mid) left.push(item)else if (item > mid) right.push(item)else midCount++;}return sort(left).concat(new Array(midCount).fill(mid), sort(right));};
插入排序
时间复杂度是n2。 1、从第一个元素开始,该元素可认为已排序 2、取出下一个元素,在已排序的序列里面从后往前扫描。 3、如果该元素大于新元素,将该元素移到下一位置。 4、重复步骤三,直到找到已排序的元素小于或者等于新元素。 5、将新元素插入到该位置。 6、重复步骤 2-5
function sort(arr = []){const len = arr.length;for(let i = 1; i < len; i++){// 取出下一个元素let cur = arr[i];// 前面序列的位置,初始化是最后一个let prevIndex = i - 1;// 前面是已排序的,只需要找到下一个元素在已排序列的位置。while(prevIndex >= 0 && arr[prevIndex] > cur){arr[prevIndex + 1] = arr[prevIndex];prevIndex--;}arr[prevIndex + 1] = cur;}return arr;}// 另一种解法function sort(arr = []){return arr.reduce((acc, cur, curIndex)=>{if(!acc.length) return [cur];acc.some((prev, prevIndex)=>{// 前面序列有大于当前值,则把当前值放置在其前面if(prev >= cur){acc.splice(prevIndex, 0, cur);return true;}// 前面序列没有大于当前值的,把当前值放置在最后面if(prevIndex === acc.length - 1){acc.splice(prevIndex + 1, 0, cur);return true;}return false;})return acc;}, [])}
冒泡排序
时间复杂度是 n2。 1、比较相邻的元素,如果左边比右边大,交换顺序 2、每一对都执行上述比较,从开始到结束,一轮结束,最右边元素是最大元素。 3、针对所有元素执行上面操作,每轮比较元素越来越少,直到没有需要比较元素。
function sort(arr = []){const len = arr.length;let temp = 0;for(let i = len - 1; i > 0; i--){let index = 0;while(index < i){if(arr[index] > arr[index + 1]){temp = arr[index];arr[index] = arr[index + 1];arr[index + 1] = temp;}index++;}}return arr;}
选择排序
时间复杂度是n2。 1、从未排序中找出最小值,放在第一个位置 2、从剩余未排序中找出最小值,放在已排序的末尾
function sort(arr = []){let min = arr[0], minIndex = -1,temp = 0;const len = arr.length;for(let i = 0; i < len; i++){min = arr[i];minIndex = i;for(let j = i; j < len; j++){if(arr[j] < min){min = arr[j];minIndex = j;}}temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}return arr;}// 先写出书面逻辑,在用代码实现,注意边界条件。function sort(arr = []){for(let i = 0; i < arr.length; i++){// 求解剩余数组的最小值索引const min = arr.slice(i + 1).reduce((index, cur, curIndex)=>{if(arr[index] > cur) return curIndex + i + 1;return index;}, i);if(i !== min) [arr[i],arr[min]] = [arr[min],arr[i]];}return arr;}
堆排序
时间复杂度是nlogn。 https://www.cnblogs.com/chengxiao/p/6129630.html
function sort(arr = []){const len = arr.length;// 构造一个大顶堆:堆定最大,堆尾最小function heapify(arr, i){const left = i * 2 + 1; // 二叉树左节点在数组下标const right = i * 2 + 2; // 二叉树右节点在数组下标let max = i;if(left < len && arr[left] > arr[max]) max = left;if(right < len && arr[right] > arr[max]) max = right;if(max !== i){// 最大值为堆定[a[i], a[max]] = [a[max], a[i]];heapify(arr, max);}}for(let i = Math.floor(len / 2); i >= 0; i--){heapify(arr, i);};for(let i = len - 1; i > 0; i--){// 堆尾和堆定互换,最后一个最大[arr[0],arr[i]] = [arr[i], arr[0]];i--;// 调整堆定,使其继续符合堆定义heapify(arr, 0);}return arr;}
归并排序
时间复杂度是nlogn。 1、分治 2、归并排序
function sort(arr = []){if(arr.length <= 1) return arr;const mid = Math.floor(arr / 2);const l = sort(arr.slice(0,mid));const r = sort(arr.slice(mid));return Array.from({length:l.length+r.length},()=>{if(!l.length) return r.shift();if(!r.length) return l.shift();return l[0] > r[0] ? r.shift() : l.shift();})}
桶排序
function sort(arr = [], size){const min = Math.min(...arr);const max = Math.max(...arr);const bucks = Array.from({length:Math.floor((max - min) / size + 1)},()=>[]);arr.forEach(item=>{bucks[Math.floor((item - min) / size)].push(item);});return arr.reduce((acc, cur) => [...arr, ...cur.sort((a, b) => a - b)], [])}
