以下代码段是否是QuickSort的有效实现?

时间:2019-08-28 19:51:37

标签: javascript quicksort

我目前正在研究大学算法的理论领域,并且根据我对算法工作原理的了解,已经实现了Quicksort的一个版本。之后,我将其与现有解决方案进行了比较,我的实现似乎与我发现的有所不同。也许有些经验的人可以给我反馈:

function quicksort(array) {
	let leftIndex = 0
	let rightIndex = array.length - 2
	if (leftIndex >= rightIndex) {
		return array
	}
	
	let pivotIndex = array.length - 1
	let finalPivotIndex;
	
	do {
		while (array[leftIndex] < array[pivotIndex]) {
			leftIndex++
		}
		while (array[rightIndex] > array[pivotIndex]) {
			rightIndex--
		}
		if (leftIndex < rightIndex) {
			array = quickSwap(leftIndex, rightIndex, array)
		} else {
			finalPivotIndex = leftIndex
		}
	} while (leftIndex < rightIndex)
	
	if (array[finalPivotIndex] > array[pivotIndex]) {
		array = quickSwap(finalPivotIndex, pivotIndex, array)
	}
	
	let leftPivotArray = array.slice(0, finalPivotIndex)
	let rightPivotArray = array.slice(finalPivotIndex + 1)
	
	let sortedLeftArray = quicksort(leftPivotArray)
	let sortedRightArray = quicksort(rightPivotArray)
	let mergedArray = sortedLeftArray.concat([array[finalPivotIndex]])
	mergedArray = mergedArray.concat(sortedRightArray)
	return mergedArray
}

function quickSwap(firstIndex, secondIndex, array) {
	let tmp = array[firstIndex]
	array[firstIndex] = array[secondIndex]
	array[secondIndex] = tmp
	return array
}

2 个答案:

答案 0 :(得分:0)

首先,我不会为交换使用单独的函数,这通常会增加一些开销,如果涉及大型数组,则不希望这样做。

在将您的代码转换为python之后,我对其进行了测试,看来它无法正常工作,已损坏,并试图找到原因。

编辑:

我稍微更改了代码,保留了基本结构,现在看来可以正常工作:

(0)做

if (leftIndex > rightIndex){
        return array
    }

代替

if (leftIndex >= rightIndex) {
        return array
    }

并添加

if ((array.length <= 2) && (array[0] < array[1])){
        return array
    }

紧随其后 (这是伪代码未在Java(是python)中对其进行测试)

最后一块确保您在递归结束端离开函数,而无需继续对子数组进行排序

(1)以这种方式将枢轴设置为数组的中间位置,从而获得log()性能,其中length-1 quicksort的速度不比任何其他

(2)将数据透视表保存在局部变量中,而不通过索引访问它,索引后面的元素可能会更改

(3)如果您在一个简单的数组上手动执行算法,则删除最后一个if语句(array[finalPivotIndex] > array[pivotIndex]) {,您会发现该块实际上改变了您刚才所做的操作,从而导致错误的结果< / p>

希望这就是我所做的全部更改,这是我的代码(在Python中,应该类似于read),以便您可以进行比较和故障排除:

import random

def Quicksort(array):
    leftIndex = 0
    rightIndex = len(array)-2


    if(leftIndex > rightIndex): #(0)
        return array

    if(len(array) <= 2 and array[0] < array[1]):#(0)
        return array
    pivotIndex = int(len(array)/2) #(1)
    finalPivotIndex = pivotIndex

    rightIndex = len(array)-1
    pivot = array[pivotIndex] #(2)
    while True:
        while array[leftIndex] < pivot: #(2)
            leftIndex += 1
        while array[rightIndex] > pivot: #(2)
            rightIndex -= 1
        if leftIndex < rightIndex:
            array[leftIndex], array[rightIndex] = array[rightIndex], array[leftIndex] #swapping in python
            #swapping alternative (without extra function) :
            #tmp = array[leftiIndex]
            #array[leftIndex] = array[rightIndex]
            #array[rightIndex] = tmp
            #this way you save the function-call-overhead and the problem of passing the whole array to ten function and back, this could hurt the performance quite a bit
            print(array, pivot, leftIndex, rightIndex) #debugging / slows down quite a bit
        else:
            finalPivotIndex = leftIndex
            break
   # (3)
   # if(array[finalPivotIndex] > array[pivotIndex]):
   #     array[finalPivotIndex], array[pivotIndex] = array[pivotIndex], array[finalPivotIndex]
   #     print(array)

    leftPivotArray = array[0:finalPivotIndex+1]
    rightPivotArray = array[finalPivotIndex+1:]

    sortedLeftArray = Quicksort(leftPivotArray)
    sortedRightArray = Quicksort(rightPivotArray)
    mergedArray = sortedLeftArray+sortedRightArray

    return mergedArray

#how I generated the array for testing
array = []
for i in range(50):
    array.append(i)
array = random.sample(array, 50)
qsorted = Quicksort(array)
array.sort()
#testing the function against the python-implementation  --> returns true
print(qsorted == array)

答案 1 :(得分:0)

问题中的代码似乎是Hoare分区方案的一种变体,但是当它只能在原始数组上使用交换并将索引传递给quicksort函数时,它正在创建数组的切片。如果需要,我可以稍后尝试调试问题的代码,但与此同时,这是一个常规的Hoare分区方案示例,该方案使用预递增和预递减,并且仅通过在较小分区上使用递归来避免堆栈溢出,然后循环返回更大的分区。在我的系统上,使用Chrome,不到1000秒就能对1000万个值进行排序。

function quicksort(a, lo, hi) {
  while (lo < hi){
    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;
    }
    if(j - lo < hi - j){
      quicksort(a, lo, j);
      lo = j+1;
    } else {
      quicksort(a, j+1, hi);
      hi = j;
    }
  }
}

var arr = new Array(10000000)
for (i = 0; i < arr.length; i++) {
  arr[i] = parseInt(Math.random() * 1000000000);
}
console.time('measure');
quicksort(arr, 0, arr.length-1);
console.timeEnd('measure');
for (i = 1; i < arr.length; i++) {
  if(arr[i-1] > arr[i]){
    console.log('error');     
    break;
  }
}