[英]How do I fix my quicksort algorithm for larger values of n ? ( and when the array is not random)
僅當數組不是隨機數組時,我的快速排序算法才會對較大的n值失敗。 我試過在各種數組上使用該算法。 當我使用數字的隨機數組(對於n的任何值)時,它可以正常工作,但是對於包含相同值或以升序或降序排列的值的數組,它會失敗。 而且這也僅在n大約為6000時才有效。(當n <5000時,它可以完美工作)
我已經嘗試過使用其他版本的quicksort。 使用while循環而不是遞歸的循環,它可以完美地工作。 就像我已經說過的那樣,僅當非隨機數組的n大於6000時,我的算法才會失敗,對於5000或更低的算法,它會很好地工作。
void quicksort(int a[], int low, int high) {
if (low < high) {
int index = partition(a, low, high); // error
quicksort(a, low, index - 1); // error
quicksort(a, index + 1, high);
}
}
int partition(int arr[], int low, int high) {
int pivot = arr[high];
int i = low - 1;
//int j = low;
for (int j = low; j < high; j++) {
// If current element is smaller than or
// equal to pivot
if (arr[j] <= pivot) {
i++;
// swap arr[i] and arr[j]
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return (i + 1);
}
上面我有我的快速排序算法。 如果n> 6000(並且數組不是隨機的)失敗。
以下是適用於n的所有值以及任何類型的數組的代碼。
public void quicksort(int[] data, int low, int high)
{ // 1 or 0 items are sorted by default
if(high - low < 1)
return;
int left = low;
int right = high;
int pivot = data[low + (high - low) / 2];
while(left <= right)
{ // Increment left pointer until left >= pivot
while(data[left] < pivot)
left++;
// Increment right pointer until right <= pivot
while(data[right] > pivot)
right--;
// If left < right; swap values
if(left <= right)
{ int temp = data[left];
data[left] = data[right];
data[right] = temp;
left++;
right--;
}
}
// quick_sort 'lesser values'
quicksort(data, low, right);
// quick_sort 'greater values'
quicksort(data, left, high);
}
static int partition(int[] array, int low, int high) {
int j, temp, i = low + 1;
Random random = new Random();
int x = random.nextInt(high - low) + low;
temp = array[low];
array[low] = array[x];
array[x] = temp;
for (j = low + 1; j <= high; j++) {
if (array[j] <= array[low] && j != i) {
temp = array[j];
array[j] = array[i];
array[i++] = temp;
} else if (array[j] <= array[low]) {
i++;
}
}
temp = array[i - 1];
array[i - 1] = array[low];
array[low] = temp;
return i - 1;
}
終端特別在兩行顯示錯誤。 (在第一個quicksort方法中,我標記為錯誤的行)。
如果數據已經整理好,則使用arr [high](或arr [low])會導致最壞情況下O(n)的堆棧空間開銷,從而使堆棧溢出。 第二個示例使用中間元素(arr [low +(high-low)/ 2]),這對於已排序的數據或已反向排序的數據將具有最佳的堆棧空間開銷。
將分區空間開銷限制為O(log(n))的一種解決方法是在進行分區之后,檢查哪個部分較小,並且僅對較小的部分使用遞歸,然后循環返回以處理較大的部分(更新為低或根據需要將其設置為高,以便在環回之前排除現在已排序的較小部分)。
public static void quicksort(int[] arr, int low, int high)
{
while (low < high) {
int index = partition(arr, low, high);
if((index-low) <= (high-index)){ // avoid stack overflow
quicksort(arr, low, index - 1); //
low = index+1; //
}else{ //
quicksort(arr, index + 1, high); //
high = index-1; //
} //
}
}
public static int partition(int[] arr, int low, int high)
{
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
int tmp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = tmp;
return (i + 1);
}
如果有興趣,Hoare分區方案會更快:
public static void qsort(int[] a, int lo, int hi)
{
while(lo < hi){
int md = lo+(hi-lo)/2;
int ll = lo-1;
int hh = hi+1;
int p = a[md];
int t;
while(true){
while(a[++ll] < p);
while(a[--hh] > p);
if(ll >= hh)
break;
t = a[ll];
a[ll] = a[hh];
a[hh] = t;
}
ll = hh++;
if((ll - lo) <= (hi - hh)){
qsort(a, lo, ll);
lo = hh;
} else {
qsort(a, hh, hi);
hi = ll;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.