快排quicksort_递归调用

// 递归调用的
function sort1(arr, left, right) {
if (left >= right) {
return
}
let q = left, h = right; // 定义可移动的i,j
while (q < h) {
// h 先--
while (q < h && arr[h] >= arr[left]) {
h--
}
// q后++
while (q < h && arr[q] <= arr[left]) {
q++
}
if (q < h) {
// 没相遇 交换
[arr[q], arr[h]] = [arr[h], arr[q]];
}



}
// if (q != left) {
[arr[q], arr[left]] = [arr[left], arr[q]];
// console.log(11, q, left)
// }
sort1(arr, left, q - 1);
sort1(arr, q + 1, right)
}
let arr = [4, 3, 6, 1, 8, 0, 3, 2, 5]
console.log(sort1(arr, 0, 8))
console.log(arr)

非递归

function sort1(arr, left, right) {
// let st = [arr[0] , arr[arr.length - 1]]
// let st = [arr[0] , arr[arr.length - 1]]
let st = []
st.push(left)
st.push(right)

console.log(st)
while(!!st.length) {
right = st.pop()
left = st.pop()
let q = left, h = right; // 定义可移动的i,j
while (q < h) {
// h 先--
while (q < h && arr[h] >= arr[left]) {
h--
}
// q后++
while (q < h && arr[q] <= arr[left]) {
q++
}
// 相遇
if (q === h) {
break
}
// 没相遇 交换
[arr[q], arr[h]] = [arr[h], arr[q]];


}
if (q != left) {
[arr[q], arr[left]] = [arr[left], arr[q]];
}
if (left < q- 1) {
st.push(left)
st.push(q - 1)
}
if (q + 1 < right) {
st.push(q + 1)
st.push(right)
}
}

}
let arr = [4, 3, 6, 1, 8, 0, 3, 2, 5]
console.log(sort1(arr, 0, 8))
console.log(arr)

  1. ​while(arr[j]>=temp&&i<j){​
  2. ​j--; ​
  3. ​}​
  4. ​while(arr[i]<=temp&&i<j){​
  5. ​i++; ​
  6. ​} ​

这里两个while的顺序是不能改变的,想一想:

假设对如下进行排序:

快排quicksort_i++_02

如上图,6在左,9在右  我们将6作为基数。

假设从左边开始(与正确程序正好相反)

于是i 就会移动到现在的 数字 7 那个位置停下来,而  j 原来在 数字 9 那个位置 ,因为

  1. ​while(arr[j]>=temp&&i<j)​

于是,j 也会停留在数字7 那个位置,于是问题来了。当你最后交换基数6与7时,不对呀!!。

问题在于当我们先从在边开始时,那么 i 所停留的那个位置肯定是大于基数6的,而在上述例子中,为了满足 i<j 于是 j也停留在7的位置

但最后交换回去的时候,7就到了左边,不行,因为我们原本 交换后数字6在边应该是全部小于6,右边全部大于6.但现在不行了。

于是,我们必须从右边开始,也就是从基数的对面开始。