我目前正在研究大学算法的理论领域,并且根据我对算法工作原理的了解,已经实现了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
}
答案 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;
}
}