简体   繁体   English

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

[英]Is the following code snippet a valid implementation of QuickSort?

I'm currently digging into the theoretical field of algorithms for university and I've implemented a version of the Quicksort based on how I understood the algorithm works. 我目前正在研究大学算法的理论领域,并且根据我对算法工作原理的了解,已经实现了Quicksort的一个版本。 After that I've compared it to existing solutions and my implementation seems to be different than the once I've found. 之后,我将其与现有解决方案进行了比较,我的实现似乎与我发现的有所不同。 Maybe some experience people can give me feedback on this: 也许有些经验的人可以给我反馈:

 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 } 

First of all I wouldnt use a separate function just for swaping, this usually adds some overhead, you dont want that if it comes to large arrays. 首先,我不会为交换使用单独的函数,这通常会增加一些开销,如果涉及大型数组,则不希望这样做。

I tested your code after translating it to python and it seems like its not working correctly, its broken, trying to find the reason at the moment. 在将您的代码转换为python之后,我对其进行了测试,似乎它无法正常工作,已损坏,并试图找到当前原因。

EDIT : 编辑:

I changed the code a bit, leaving the basic structure and it now seems to work properly: 我稍稍更改了代码,保留了基本结构,现在看来可以正常工作:

(0) do (0)做

if (leftIndex > rightIndex){
        return array
    }

instead of 代替

if (leftIndex >= rightIndex) {
        return array
    }

and add 并添加

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

right after it (this is rather pseudo code didnt test it in java (was python)) 就在它之后(这是伪代码未在Java中进行测试(是python))

the last block makes sure you leave the function once youre at the resursion end end not need to continue sorting the sub-array 最后一块确保您在递归结束端离开函数,而无需继续对子数组进行排序

(1) set the pivot to the middle of the array this way you get the log() perfaormance, with length-1 quicksort is not quicker than any other (1)以这种方式将枢轴设置为数组的中间位置,即可获得log()性能,其中length-1 quicksort的速度并不比其他任何方法都要快

(2) save the pivot in a local variable and not access it by index, the element behind the index might change (2)将枢轴保存在局部变量中,而不通过索引访问它,索引后面的元素可能会更改

(3) remove the last if statement (array[finalPivotIndex] > array[pivotIndex]) { if you do the algorithm by hand on a simple array you see that this block actually changes back what you just did, this way you end up with a wrong result (3)删除最后一个if语句(array[finalPivotIndex] > array[pivotIndex]) {如果您是在一个简单的数组上手动执行算法,则会看到此块实际上改变了您刚刚做的事情,这样最终错误的结果

hope thats all I changed, here is my code (in Python, should be similar to read) so you can compare and troubleshoot : 希望这就是我所做的全部更改,这是我的代码(在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)

The code in the question appears to be a variation of Hoare partition scheme, but it's creating slices of an array, when it can just use swaps on the original array, and pass indexes to the quicksort function. 该问题中的代码似乎是Hoare分区方案的一种变体,但是它正在创建数组的切片,此时它只能在原始数组上使用交换,并将索引传递给quicksort函数。 If wanted, I can try to debug the question's code later, but in the meantime, here is an example of a conventional Hoare partition scheme that uses pre-increment and pre-decrement, and avoids stack overflow by only using recursion on the smaller partition, and looping back for the larger partition. 如果需要,我可以稍后尝试调试问题的代码,但与此同时,这是一个常规的Hoare分区方案示例,该方案使用预递增和预递减,并且仅通过在较小分区上使用递归来避免堆栈溢出,然后循环返回更大的分区。 On my system, using Chrome, it takes less than 2 seconds to sort the 10 million values. 在我的系统上,使用Chrome浏览器对1000万个值进行排序所需的时间不到2秒。

 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; } } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM