使用随机数据透视在Javascript中实现QuickSort

时间:2015-07-10 04:24:50

标签: javascript algorithm quicksort

我已经在javascript中编写了quicksort,但我想尝试使用随机数据创建一个,而不是选择数组中的第一个或最后一个元素:

   function qsort(a) {
     //base case
     if (a.length === 0) return [];

     //setting the pivot as the last element. 
     var left = [],
         right = [],
         pivot = a[a.length - 1];

     //look before the pivot. everything less than it goes to its left, more than it, to its right.
     for (var i = a.length - 2; i >= 0; i--) {
         a[i] < pivot ? left.push(a[i]) : right.push(a[i]);
     }
     //you then do this recursively until the basecase, pivoting/sorting all sub arrays, then concatenating the left side with the pivot and the right side.
     return qsort(left).concat(pivot, qsort(right));
 }

 console.log(qsort([9, 8, 7, 6, 10, 5]));//[5, 6, 7, 8, 9, 10]

我以为我可以这样做:

pivot = a[Math.floor(Math.random() * a.length)];

我被绊倒的地方是,一旦你将数据分配为数组中的随机值,我的for循环的参数将不再有效。在此函数/ for循环中考虑随机数据透视并使其正确排序的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

Amadan提供的解决方案无法处理包含非唯一值的数组。以下解决方案应该能够处理任何整数数组,包括具有非唯一值的整数数组。例如[4,6,6,3,4,4,2]

function quickSort (arr, left = 0, right = arr.length - 1) {
  if (arr.length > 1) {
    const position = partition(arr, left, right)
    if (left < position - 1) quickSort(arr, left, position - 1)
    if (position < right) quickSort(arr, position, right)
  }
  return arr
}

function partition (arr, left, right) {
  const pivot = arr[Math.floor(Math.random() * (right - left + 1) + left)]

  while (left <= right) {
    while (arr[left] < pivot) {
      left++
    }
    while (arr[right] > pivot) {
      right--
    }
    if (left <= right) {
      swap(arr, left, right)
      left++
      right--
    }
  }
  return left
}

function swap (arr, left, right) {
  const temp = arr[left]
  arr[left] = arr[right]
  arr[right] = temp
}

module.exports = { quickSort }

答案 1 :(得分:1)

显而易见的事情是制作一个枢轴阵列,在这里你可以填充与枢轴相等的元素。

另一种方法是记住枢轴的索引以及值,并在循环的顶部跳过它(它将覆盖整个数组):

if (i == pivotIndex) continue;

另一种通常在C中用来避免分配的方法是在一个数组中完成所有操作。

function qsort(array, start, end) {
  if (start === undefined) {
    start = 0;
    end = array.length - 1;
  } else if (start >= end) {
    return array;
  }
  var rStart = start, rEnd = end;
  var pivot = array[Math.floor(Math.random() * (end - start + 1) + start)];
  while (start < end) {
    while (array[start] <= pivot) start++;
    while (array[end] > pivot) end--;
    if (start < end) {
      var temp = array[start];
      array[start] = array[end];
      array[end] = temp;
    }
  }
  qsort(array, rStart, start - 1);
  qsort(array, start, rEnd);
  return array;
}

console.log(qsort([9, 8, 7, 6, 10, 5]));//[5, 6, 7, 8, 9, 10]