分区在我的快速排序功能中不起作用

Partition not working in my quicksort function

我已经研究这个问题一段时间了,但我的分区函数无法正常工作。我增加起始值,直到它达到小于枢轴的值,反之亦然,我的终点指针。我用我的起点和终结点交换值。然后我用我的起点和枢轴交换价值。我错过了什么吗?


function quickSort(arr, start, end) {
    if (start >= end) {
        return
    }


    let index = partition(arr, start, end)

    quickSort(arr, start, index - 1)
    quickSort(arr, index + 1, end)
    return arr
}

function partition(arr, start, end) {
    let pivotIndex = end 
    let pivotValue = arr[end]
    let endPointer = arr[end - 1] //end pointer start w/ value left of pivot

    while (start <= end) {
        if (arr[start] < pivotValue) {
            start++
        } else {
            swap(arr,start, endPointer)
        }
        if (arr[endPointer] > pivotValue) {
            endPointer--
        } else {
            swap(arr,start, endPointer)
        }
    }

    swap(arr,start, pivotIndex)
    return start


}

function swap(arr, a, b) {
    let temp = arr[a]
    arr[a] = arr[b]
    arr[b] = temp 
}

let arr = [0,5,2,1,6,3]
console.log(quickSort(arr, 0, arr.length - 1))

配分函数似乎是 Hoare 的变体。有几个问题(endPointer 应该是 end-1,而不是 arr[end-1];while (start < endPointer); if/else/swap if/else/swap 应该是 while / while / swap / increment indexes again / ...) 并使用最后一个值作为基准意味着向后扫描将需要检查它是否已递减到开始以下。通常 Hoare 依靠 运行 进入主元,所以主元是从中间选择的,或者至少不是从第一个或最后一个元素。下面是一个 "classic" Hoare 的例子,分区代码合并到快速排序函数中:

function quicksort(a, lo, hi) {
  if(lo >= hi)
    return;
  var p = a[Math.floor(lo+(hi-lo)/2)];
  var i = lo - 1;
  var j = hi + 1;
  var t;
  while (true){
    while (a[++i] < p);
    while (a[--j] > p);
    if (i >= j)
      break;
    t = a[i];
    a[i] = a[j];
    a[j] = t;
  }
  quicksort(a, lo, j);
  quicksort(a, j+1, hi);
}

由于代码使用最后一个值作为主元值,替代方案是 Lomuto 分区方案:

function quicksort(a, lo, hi) {
  if(lo >= hi)
    return;
  var p = a[hi];
  var i = lo;
  var j;
  var t;
  for(j = lo; j < hi; j++){
    if(a[j] < p){
      t = a[i];
      a[i] = a[j];
      a[j] = t;
      i++;
    }
  }
  t = a[i];
  a[i] = a[hi];
  a[hi] = t;
  quicksort(a, lo, i-1);
  quicksort(a, i+1, hi);
}