我是高中四年级APCS班的学生,正在为期中学习。 我的老师说下面是编码的最佳方法 “升序排序-选择右枢轴,然后在分区时先看左边/降序排序-选择左枢轴,当分区时,先看看右手”
起初我不明白为什么,所以我尝试了所有情况 我已经尝试了升序排序
(1)选择右枢轴/首先看向左
(2)选择右枢轴/首先看向右
(3)选择左枢轴/首先看向左
(4)选择左枢轴/首先看向右
但是我只有(1)类型可以工作。其余3个版本中存在一些逻辑错误。根据经验,我知道(2)〜(4)很难编码 通过经验并在纸上写下来,我知道如果我使用正确的轴心并首先看正确的东西,那么使用QuickSort的常规方法会出现问题。
总结:问题 [1](2)〜(4)比(1)难编码的确切原因是什么? [2]你们中任何一位出色的编码员都能帮助我完成(2)〜(4)
以下是适用于Java的版本(1)的代码
///* MOST SIMPLE VERSION OF QUICKSORT. ASCENDING, END PIVOT, LEFT FIRST
SWEEP, LEFT & RIGHT COMPARISON
public static void endPivSortV1(int[] a, int start, int end) {
if(start < end) {
int pVal = a[end];
int left = start;
int right = end;
//QUESTION: right = end - 1
while(true) {
while(a[left] <= pVal && left < right) //left,
left++;
while(a[right] >= pVal && left < right)
right--;
if(left == right)
break;
swap(a, left, right);
}
swap(a, left, end);
endPivSortV1(a, start, left - 1);
endPivSortV1(a, left + 1, end);
}
} //*/
我已经复制并粘贴了此代码,并对其进行了部分更改以创建版本(2)〜(4),但它们无法正常工作。
public static void endPivSortV2(int[] a, int start, int end) {
if(start < end) {
int pVal = a[end];
int left = start - 1;
int right = end + 1;
while(true) {
while(a[right--] >= pVal && left < right);
while(a[left++] <= pVal && left < right);
if(left == right)
break;
swap(a, left, right);
}
swap(a, left, end);
endPivSortV2(a, start, left - 1);
endPivSortV2(a, left + 1, end);
}
}
这是我尝试首先看右边而不是看左边的那个。 (而右移的那句话位于左移的那句的前面)我知道代码超级草率,充满了错误,但由于我在高中只写了一年的兼职书,所以让我有些懈怠...
谢谢。这是我在这里的第一篇文章,所以不要对我太刻苦:D
答案 0 :(得分:0)
(1)和(4)本质上是相同的,您可以依靠扫描进入枢轴值作为停止循环的一种方式,而不必进行边界检查。对于(1),... <枢轴到达右侧的枢轴时将停止。对于(4),...>枢轴如果到达左侧的枢轴,则会停止。
(2)和(3)需要检查,以使扫描索引不会超出数组的范围,或者您可以通过将枢轴交换到数组的另一端并使用逻辑来“作弊”来自(1)或(4)。
注意-所有这些都是Lomuto分区方案的变体。还有Hoare分区方案,该方案通常选择中间值作为枢轴,并从左右扫描(两次扫描使用单独的索引)。当索引彼此交叉时,扫描停止。