Java 快堆破碎
我正在尝试并行化快速排序,所以我首先编写了串行版本,在两个分区上使用分区和递归排序。这很有效。。直到>100000的大小,在这种情况下,如果其中一个分区太大,它将永远不会完成。我不明白这是为什么。它将在100k时运行13-15毫秒,但在120k时,它将在大约相同的时间运行,或者根本不运行 对于我的分区,我根据当前分区的第一个、中间和最后一个元素的中间值选择轴,如果它们相等,则转到最后一个元素 这是我的分区:Java 快堆破碎,java,algorithm,sorting,quicksort,Java,Algorithm,Sorting,Quicksort,我正在尝试并行化快速排序,所以我首先编写了串行版本,在两个分区上使用分区和递归排序。这很有效。。直到>100000的大小,在这种情况下,如果其中一个分区太大,它将永远不会完成。我不明白这是为什么。它将在100k时运行13-15毫秒,但在120k时,它将在大约相同的时间运行,或者根本不运行 对于我的分区,我根据当前分区的第一个、中间和最后一个元素的中间值选择轴,如果它们相等,则转到最后一个元素 这是我的分区: private static int partition(int low, int hi
private static int partition(int low, int high, int[] array){
//get median of first, last, and middle element in our section
int lVal, hVal, mVal, pIndex, pVal;
lVal = array[low];
hVal = array[high];
mVal = array[((high-low+1)/2) + low];
//System.out.println("LOW: " + low + "HIGH: " + high);
if (lVal < hVal && lVal > mVal || lVal > hVal && lVal < mVal){
pIndex = low;
//System.out.println("Picking low index: " + low);
} else if (hVal < lVal && hVal > mVal || hVal > lVal && hVal < mVal){
pIndex = high;
//System.out.println("Picking high index: " + high);
} else if (mVal < hVal && mVal > lVal || mVal > hVal && mVal < lVal){
pIndex = (high-low+1)/2+low;
//System.out.println("Picking middle index: " + ((high-low+1)/2)+low);
} else {
pIndex = high;
}
pVal = array[pIndex];
//put pivot at the back of our chunk
int temp = array[pIndex];
array[pIndex] = array[high];
array[high] = temp;
//printArray();
//two pointer method.. high and low.. move them and swap if low > pivot and high < pivot
int left = low;
int right = high - 1;
pIndex = 0;
while (left <= right){
while(left <= high && array[left] < pVal){
left++;
}
while(right >= low && array[right] > pVal){
right--;
}
//if both elements at the pointers are on the wrong side we swap
if(left < right){
temp = array[left];
array[left] = array[right];
array[right] = temp;
left++;
right--;
//printArray();
}
}
//need to get pivot from high to where the low pointer ended
temp = array[left];
array[left] = array[high];
array[high] = temp;
//printArray();
return left;
}
任何关于为什么这会在某一点冻结的想法都是非常棒的。我运行了另一种我在互联网上找到的分区,它在我给它的任何大小上都可以正常运行,但我想知道这有什么问题。这是我用来测试它的单元测试
@Test
public void testSortStandard() throws Exception {
int size = 100000;
//test randoms to 10000
int[] a = new int[size];
Random r = new Random();
for(int i = 0; i < size; i++){
a[i] = r.nextInt();
}
QuickSort.sort(0, a.length-1, null, a);
testIsSorted(a);
}
@测试
public void testSortStandard()引发异常{
整数大小=100000;
//测试随机数为10000
int[]a=新的int[size];
随机r=新随机();
对于(int i=0;i
它只是继续跑啊跑啊跑。我有一种感觉,它只是一次又一次地对事物进行划分,这是一种浪费。这种行为告诉我的是,当处理足够大的大小以使错误出现时,会出现一个相对不可描述的错误。我很想知道,如果你在一个循环中调用quicksort数千次,但输入量要小得多,这样会不会发生在较小的数组上,从而增加遇到该错误的几率。是的,我刚刚做了一个,它只在10000个数组上调用它,但它会对一个新数组进行100次排序,如果我运行它5-10次,它将打破这个错误同样的方式。所以,谢谢你帮我把范围缩小到这一点。现在我只需要找到bug。不确定它会是什么。继续缩小大小并增加频率,直到你得到一个小到可以轻松调试的机箱。我建议您在调用quicksort之前,首先复制正在排序的数据,以便在排序失败时对其进行详细检查。我刚刚通过一个新的单元测试发现,这是由重复的数字引起的,因为我使用所有一个数字作为数组运行了一个测试,它也做了同样的事情。我以为我已经处理好了,但显然没有。我认为当重复的数字位于只有2的分区中或位于数组的边界上时,就会发生这种情况。谢谢你的帮助@Tylerhylmuth如果你有一个问题的解决方案,你可能应该把它作为一个答案发布出来,这样网站的访问者就更容易发现问题所在以及如何解决问题。:-)
@Test
public void testSortStandard() throws Exception {
int size = 100000;
//test randoms to 10000
int[] a = new int[size];
Random r = new Random();
for(int i = 0; i < size; i++){
a[i] = r.nextInt();
}
QuickSort.sort(0, a.length-1, null, a);
testIsSorted(a);
}