快速排序:
1.找一个基准值,比如把数组第一项作为基准值,作为数组内剩下的比较项;
拿基准值与数组内的每一项去比较,大于这个基准值的push进right数组内,小于的push到left数组内。
2.再用递归把left和right两个数组分别再按照这种逻辑拆分成左右数组,直到传入的数组length<1 length为0时,作为递归的终止条件。
3.终止条件return出去的要是一个arr 或者是一个空数组(因为没值符合了,已经拆分完了),为什么要返回空数组呢?而不是直接return掉呢?
因为最后是用拼接的方式把符合条件的放入到一个数组内了。并且是用...扩展运算符,所以只能是一个数组。
// 快速排序思想: // 排队的时候,随便找一个人:小明 遍历一次,比小明矮的站在左边,反之站右边 var arr1 = [3, 44, 13, 8, 9, 7, 1, 2]; function quickSort1(arr) { if (arr.length < 1) return arr; let flag = arr[0]; let left = []; let right = []; for (let i = 1; i < arr.length; i++) { if (flag > arr[i]) { left.push(arr[i]) } else { right.push(arr[i]) } } // 第一种写法 let l = quickSort1(left); let r = quickSort1(right); return [...l, flag, ...r]; // 第二种写法 return quickSort1(left).concat([flag]).concat(quickSort1(right)) } var res1 = quickSort1(arr1); console.log(res1); // [1, 2, 3, 7, 8, 9, 13, 44] // 复杂度:O(n * lgn)以2为底的x次方,一分为二 // 缺点: // 有了left和right 两个变量,每次递归的时候都会声明这两个变量,占用空间太多
原地快排:
由于快排每次递归会生成left和right两个数组(两个引用内存空间)浪费内存,我们用原地排序进行优化:
function qsort(arr, start, end) { if (start >= end) return let i = start, j = end let mid = arr[start] while (i < j) { // 当前后面的项>前面的,就让后面的j--,从后往前找 while (i < j && arr[j] >= mid) { j-- } // 直到打破了上面的while循环:后面的<前面的,拿到了打破条件的这个j的索引, // 那就把当前这一项赋值给前面的这一项(交换位置) if (i < j) { arr[i] = arr[j] } // 如果当前项<后面项,那就i++(前面的当然要排到前面了),从前往后查找 while (i < j && arr[i] <= mid) { i++ } // 直到当前项>后面项,那就交换位置(前面项大于后面项的话应该把前面项放在后面) if (i < j) { arr[j] = arr[i] } } // 继续 qsort(arr, start, i - 1) qsort(arr, i + 1, end); // 当此轮循环i>=j的时候,打破了上面的循环,那么就让i对应的项变为mid(基准比较对象) arr[i] = mid return arr; } let array = [14, 8, 29, 7, 25, 13, 55, 14, 95, 8, 11, 6] let resResult = qsort(array, 0, array.length - 1) console.log(resResult);
二分排序
var arr = [15, 2, 3, 6, 71, 28, 24, 25, 5, 1]; function fn(arr, start, end) { if (start > end) return []; if (start == end) return [arr[start]]; let center = Math.floor((start + end) / 2); let left = fn(arr, start, center); let right = fn(arr, center + 1, end); let r = []; while (left.length > 0 || right.length > 0) { if (left[0] < right[0]) { r.push(left.shift()) } else { r.push(right.shift()) } if (left.length === 0) { r = r.concat(right) break; } else if (right.length === 0) { r = r.concat(left) break; } } return r; } var res = fn(arr, 0, arr.length - 1); console.log(res);