[英]Recursive QuickSort multiple bugs
我已經嘗試修復此遞歸快速排序程序大約三天了,我相信其中存在錯誤,因為它可以對較小的數組進行排序,但對較大的數組進行了錯誤的排序。
該代碼使用三位數中值技術從a[start] to a[end]
對數組進行排序。 我相信問題在於分區。 請看一看
import java.util.*;
public class QuickSort
{
public static void main(String [] args)
{
int [] arr = {6,4,1,14, 13,20,7,10,9,2,17};
System.out.println(Arrays.toString(arr));
quickSort(arr, 0,arr.length-1);
System.out.println(Arrays.toString(arr));
System.out.println("is the array sorted? " + isSorted(arr));
}
public static void quickSort(int[] a, int start, int end)
{
if(end-start > 0) //base case for zero or one element?
{
int pivotPosn = partition(a,start,end);
quickSort(a,start, pivotPosn-1);
quickSort(a,pivotPosn+1, end);
}
}
/***
* swap - Swaps two values in an array.
***/
private static void swap(int [] a, int index1, int index2)
{
int temp = a[index1];
a[index1] = a[index2];
a[index2] = temp;
}
private static boolean isSorted(int [] a)
{
int i = a.length;
boolean result = true;
for(int j = 1; j<i; j++)
{
if(a[j-1] > a[j])
{
result = false;
}
}
return result;
}
private static int medianOfThreeIndex(int [] a, int start, int end)
{
int mid= start + (end-start)/2; //find the middle of the array
int vs = a[start];
int vm = a[mid];
int ve = a[end];
if (vs >= vm && vm >= ve)
{
return mid;
}
else if (vm >= vs && vs >= ve)
{
return start;
}
else
{
return end;
}
}
private static int partition(int [] a, int start, int end)
{
int boundary,pivot,pivotPosn;
pivotPosn = medianOfThreeIndex(a,start,end);
pivot = a[pivotPosn];
boundary = start;
swap(a,pivotPosn,end);//moving pivot to the right
for(int curr = start+1; curr<=end;curr++)
{
if(a[curr]<pivot)
{
boundary++;
swap(a,boundary,curr);
}
}
swap(a,end,boundary); //swap pivot value back to its final place
return boundary;
}
}
輸出為[6, 4, 1, 9, 7, 13, 14, 10, 17, 20, 2]
我不知道我在做什么錯了:(
您有幾個錯誤,主要是我認為您不太了解三位數的中位數應該做什么以及在哪里使用它。 特別是-應該使用它來選擇樞軸,而不要在陣列上進行任何交換。 我假設您的swap方法可以正常工作。
您首先可以忘記三個樞軸選擇的中位數,然后使程序的主要部分工作。 三個樞軸選擇的中位數只是為了提高性能,而不是選擇數組的起點作為樞軸。 因此,讓我們更改代碼以首先執行此操作:
private static int partition(int [] a, int start, int end)
{
int boundary,pivotPosn, pivot,bigStart;
pivotPosn = start;
pivot = a[pivotPosn];
boundary = start;
//Got rid of bigStart - it's not needed...
swap(a,pivotPos,end); //Move your pivot value to the "right" or end of array
// Note - it is fine to store the pivot at the "left" or start as
// the OP originally did - in which case the following for
// loop should run from start+1 to end inclusive and the
// boundary++ would come before the swap.
for(int curr = start; curr<end;curr++)
{
if(a[curr]<pivot)
{
swap(a,boundary,curr);
boundary++;
}
}
swap(a,end,boundary); //swap your pivot value back to its final place
return boundary;
}
然后查看您的quicksort方法。 請記住,我們現在暫時忽略了meanOfThree。 您會發現不需要的邊緣情況-2成員數組。 更簡單的是:
public static void quickSort(int[] a, int start, int end)
{
if(end-start > 0) //base case for zero or one element? already
{
int pivotPosn = partition(a,start,end);
quickSort(a,start, pivotPosn-1);
quickSort(a,pivotPosn+1, end);
}
}
這樣,它將起作用:)
但是-您可能想回到meanOfThree。 還記得我們把pivotPosn = start
放在pivotPosn = start
嗎?
將其更改為pivotPosn = medianOfThree(a,start,end);
(或任何您喜歡的東西,只要它在數組中-即可播放)。
然后,percentOfThree需要返回數組開始,中間和結尾之外的中間值的索引。 我建議這樣更改您的方法(不是最緊湊,但易於閱讀):
private static int medianOfThreeIndex(int [] a, int start, int end)
{
int mid= start + (end-start)/2; //find the middle of the array
int vs = a[start];
int vm = a[mid];
int ve = a[end];
if (vs >= vm && vm >= ve)
{
return mid;
}
else if (vm >= vs && vs >= ve)
{
return start;
}
else
{
return end;
}
}
有了-完成。 我到處找了一個教程,以防您不清楚算法,發現關於此的Wikipedia文章相當不錯。
您的代碼對我來說似乎很奇怪。 看看http://www.vogella.com/tutorials/JavaAlgorithmsQuicksort/article.html那里的代碼對我來說似乎更清晰了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.