我实现了快速排序算法,该算法在算法简介(Cormen,第3版)7.1中提供了伪代码
当我尝试使用小尺寸数组的算法时,结果为true。但是当我尝试使用N = 50000时,数组已经像这样排序了;N = {1,2,3,…,50000};
它给出了StackOverflowError。我认为这是因为函数自身递归50000次。QuickSort(A,0,49999)=> QuickSort(A,0,49998)=> QuickSort(A,0,49997)…继续。
我可以解决这个问题吗?还是我应该使用不同的枢轴位置?
这是我的代码;
public void sort(int[] arr){ QuickSort(arr, 0, arr.length - 1); } private void QuickSort(int[] A, int left, int right){ if(left < right){ int index = Partition(A, left, right); QuickSort(A, left, index - 1); QuickSort(A, index + 1, right); } } private int Partition(int[] A, int left, int right){ int pivot = A[right]; int wall = left-1; for(int i=left; i<right; i++){ if(A[i] <= pivot){ Swap(A, ++wall, i); } } Swap(A, wall + 1, right); return wall + 1; } private void Swap(int[] A, int x, int y){ int keeper = A[x]; A[x] = A[y]; A[y] = keeper; }
是的,此透视图方案不是排序数组的正确选择。如您所注意到的,它会导致非常不平衡的分区,导致O(N ^ 2)复杂性和非常深的递归级别。 有一些方法可以改善此行为。例如,您可以对像这样的枢轴使用随机索引,也可以pivotIdx = start + rand() % (end- start+1);选择三位数中值方法(索引范围内第一个,最后一个和中间元素的中位数)。
pivotIdx = start + rand() % (end- start+1);
PS避免堆栈溢出的选项-首先对较短的段调用递归,然后对较长的段调用递归。
https://zh.wikipedia.org/wiki/Quicksort#Choice_of_pivot