# 1.我的目的

很久没有写过基本的排序算法了，想实现一下；最近应该会把基本排序算法都回忆一遍。写一个记录一个吧(以下代码都在leetcode上跑通过所有数据且时间复杂度在预期范围内)

# 2.代码

let s = [1,2,5,3,5,1,4];
let funcA = function (arr) {
let l = parseInt(arr.length/2);
if (l > 0) {
let left = funcA(arr.slice(0,l));
let right = funcA(arr.slice(l));
let leftIndex = left.length;
let rightIndex = right.length;
let resp = [];
let leftTemp = 0;
let rightTemp = 0;
while (leftTemp < leftIndex && rightTemp < rightIndex) {
if (left[leftTemp] < right[rightTemp]) {
resp.push(left[leftTemp]);
leftTemp++;
}
else {
resp.push(right[rightTemp]);
rightTemp++;
}
};
if (leftTemp === leftIndex) {
resp = [...resp, ...right.slice(rightTemp)];
}
if (rightTemp === rightIndex) {
resp = [...resp, ...left.slice(leftTemp)];
}
return resp;
} else {
return arr;
}
}
console.log(funcA(s))


let sortList = [2,34,3,6,1,21,53,10,21,6]
let quickSort = function (left, right, sortList) {
let sign = sortList[right]
let leftSign = left
let rightSign = right
while (leftSign < rightSign) {
while (sortList[leftSign] <= sign && leftSign < rightSign) {
leftSign++
}
sortList[rightSign] = sortList[leftSign]
while (sortList[rightSign] >= sign && leftSign < rightSign) {
rightSign--
}
sortList[leftSign] = sortList[rightSign]
}
sortList[leftSign] = sign
if (left < leftSign-1) {
quickSort(left, leftSign-1, sortList)
}
if (right > rightSign+1) {
quickSort(rightSign+1, right, sortList)
}
}
quickSort(0, sortList.length-1, sortList)
console.log(sortList)


在最优情况下是一个等比数列 也就是2(1- 2 k 2^k )/(1-2) = n 得到 k = l o g 2 n log_2{n} , 然后每层都需要排列n个数，所以是O(n l o g 2 n log_2{n} )
在最坏情况，也就是不能刚好二分的去排列了，层数就会变高，最坏情况就是每层都在最左边或者最右边，那么也就是要排列n层，事件复杂度就是O( n 2 n^2 )

let sortList = [-4, 0, 7, 4, 9, -5, -1, 0, -7, -1]
let lastLeaf = parseInt((sortList.length - 1) / 2)
let sortOnetime = function (arr, i, lenSign) {
let sign = i
if (arr[2 * i + 1] !== undefined && arr[2 * i + 1] > arr[sign] && (2 * i + 1) <= lenSign) {
sign = 2 * i + 1
}
if (arr[2 * i + 2] !== undefined && arr[2 * i + 2] > arr[sign] && (2 * i + 2) <= lenSign) {
sign = 2 * i + 2
}
if (sign !== i){
let temp = arr[sign]
arr[sign] = arr[i]
arr[i] = temp
sortOnetime(arr, sign, lenSign)
}
}
// 初始化一个升序堆
for (let i = lastLeaf; i >= 0; i--) {
sortOnetime(sortList, i, sortList.length - 1)
}
// 交换首尾并重新排序堆
for (let i = sortList.length - 1; i > 0; i--) {
sortOnetime(sortList, 0, i)
let temp = sortList[i]
sortList[i] = sortList[0]
sortList[0] = temp
}
console.log(sortList)


一开始自己犯了两个错误：
1.每次在排序堆的时候左边右边比较如果都大于父节点，我会对两个子节点自身继续进行排序， 而这样是不必要的，大大增加了时间复杂度 ，哭; 因为父节点的子节点肯定是各自有序的，是调整之后可能对其有序造成影响，所以只需要取递归排序调换的那一边(也就是最大的那一边)就可以了
2.在对换堆顶和堆尾元素之后，要记得把重排序的长度减1,被影响的节点排序时也应遵守这个长度限制

02-01 456

07-19 2万+
05-30 1261
11-06 2万+
08-17 7万+
07-21 597
11-30 1353
04-22 52
08-20
12-18 41万+