Java 实现快速排序以对其内容具有受限/无访问权限的列表进行排序
我试图实现快速排序算法,对不允许直接访问其元素的列表进行排序。我应该只使用两种方法对Java 实现快速排序以对其内容具有受限/无访问权限的列表进行排序,java,algorithm,sorting,data-structures,quicksort,Java,Algorithm,Sorting,Data Structures,Quicksort,我试图实现快速排序算法,对不允许直接访问其元素的列表进行排序。我应该只使用两种方法对列表进行排序:swap和compare,而不使用仅用于调试目的的toString方法。我选择了子数组的中间元素作为轴心。使用函数调用期间传递的比较器对象进行比较 我使用随机生成的列表运行了一些JUnit测试,其中几乎所有列表都得到了排序(更新:在运行了更多的测试之后,我发现了更多算法失败的情况)。然而,(其中一种情况)当我尝试分区一个4元素子数组时,我的算法失败了,其中键按如下顺序排列:[最小、最大、大、小] 下
列表进行排序:swap
和compare
,而不使用仅用于调试目的的toString
方法。我选择了子数组的中间元素作为轴心。使用函数调用期间传递的比较器
对象进行比较
我使用随机生成的列表运行了一些JUnit测试,其中几乎所有列表都得到了排序(更新:在运行了更多的测试之后,我发现了更多算法失败的情况)。然而,(其中一种情况)当我尝试分区
一个4元素子数组时,我的算法失败了,其中键按如下顺序排列:[最小、最大、大、小]
下面是传递列表的JUnitTest-[0,3,2,1]:
private static final Comparator<Integer> INTEGER_COMPARATOR = new IntegerComparator();
@Test
public void customTest() {
SwapList<Integer> customList;
AbstractSorter<Integer> customSorter;
customList = new ArrayBasedSwapList<Integer>(new Integer[] { 0, 3, 2, 1 });
customSorter = new QuickSorter<Integer>(customList,
INTEGER_COMPARATOR);
SwapList<Integer> result = customSorter.sort();
System.out.println("Result: " + result.toString());
assertTrue(result.isSorted(INTEGER_COMPARATOR));
}
我放了一些println语句,并在代码中添加了一个indent
变量以进行调试。以下是运行测试后的输出:
quicksort(0, 3)
Inside partition(0, 3)
pivotIndex = 1
Initially: [0, 3, 2, 1]
i = 1, pivotIndex = 1, j = 3
After 1st swap: [0, 1, 2, 3]
Pivot was swapped
i = 2, pivotIndex = 3, j = 2
After 2nd swap: [0, 1, 3, 2]
i = 2, pivotIndex = 3, j = 2
p = 2
quicksort(0, 1)
Inside partition(0, 1)
pivotIndex = 0
Initially: [0, 1, 3, 2]
i = 0, pivotIndex = 0, j = 0
After 2nd swap: [0, 1, 3, 2]
i = 0, pivotIndex = 0, j = 0
p = 0
quicksort(0, -1)
quicksort(1, 1)
quicksort(3, 3)
结果:[0,1,3,2]
问题出在分区(0,3)
中,其中第二个swap语句逆转了第一个swap的效果。有人能帮我修改一下快速排序算法吗?我可能应该添加一个if
语句,这样第二次交换只在pivotIndex
处的元素I
>时发生
代码如下:
包裹分拣机;
导入java.util.Comparator;
导入结构.SwapList;
公共类QuickSorter扩展了AbstractSorter{
//字符串缩进=”;
公共快速排序器(SwapList、Comparator和Comparator){
超级(列表、比较);
}
@凌驾
公共交换列表排序(){
快速排序(0,list.size()-1);
退货清单;
}
私有void快速排序(int firstIndex,int lastIndex){
//System.out.println(缩进+快速排序(“+firstIndex+”,“+lastIndex+”);
//缩进+=“”;
如果(第一个索引<最后一个索引){
int p=分区(第一个索引,最后一个索引);
//System.out.println(缩进+“p=“+p”);
快速排序(第一索引,p-1);
快速排序(p+1,最新索引);
}
//缩进=缩进子串(2);
}
私有int分区(intfirstindex,intlastindex){
//System.out.println(indent+“内部分区(“+firstIndex+”,“+lastIndex+”));
int pivotIndex=(firstIndex+lastIndex)/2;
//System.out.println(缩进+“pivotIndex=“+pivotIndex”);
int i=第一索引;
int j=最新索引;
而(i=0&&i
附加代码:
private void quicksort(int firstIndex, int lastIndex) {
//System.out.println(indent + "quicksort(" + firstIndex + ", " + lastIndex + ")");
//indent+=" ";
if(firstIndex < lastIndex) {
int p = partition(firstIndex, lastIndex);
//System.out.println(indent + "p = " + p);
if (firstIndex < p - 1)
quicksort(firstIndex, p - 1);
if (p < lastIndex)
quicksort(p, lastIndex);
}
// indent = indent.substring(2);
}
private int partition(int firstIndex, int lastIndex) {
//System.out.println(indent + "Inside partition(" + firstIndex + ", " + lastIndex + ")");
int pivotIndex = (firstIndex + lastIndex) / 2;
//System.out.println(indent + "pivotIndex = " + pivotIndex);
int i = firstIndex;
int j = lastIndex;
while (i <= j) {
while(list.compare(i, pivotIndex, comparator) < 0) {
i++;
}
while(list.compare(j, pivotIndex, comparator) > 0) {
j--;
}
//System.out.println(indent + "Initially: " + list.toString());
//System.out.println(indent + "i = " + i +", pivotIndex = " + pivotIndex + ", j = " + j);
if(i <= j) {
list.swap(i, j);
//System.out.println(indent + "After 1st swap: " + list.toString());
if(i == pivotIndex) {
pivotIndex = j;
//System.out.println(indent + "Pivot was swapped");
}
else if(j == pivotIndex) {
pivotIndex = i;
//System.out.println(indent + "Pivot was swapped");
}
i++;
j--;
//System.out.println(indent + "i = " + i +", pivotIndex = " + pivotIndex + ", j = " + j);
}
}
// list.swap(pivotIndex, i);
//System.out.println(indent + "After 2nd swap: " + list.toString());
//System.out.println(indent + "i = " + i +", pivotIndex = " + pivotIndex + ", j = " + j);
return i;
}
package test;
import java.util.Comparator;
import java.util.Random;
public class Test
{
private static final Comparator<Integer> INTEGER_COMPARATOR = new IntegerComparator();
public static void main(String args[]) {
SwapList<Integer> customList;
AbstractSorter<Integer> customSorter;
do {
Random r = new Random();
int length = r.nextInt(10);
Integer[] test = new Integer[length];
for(int j = 0; j < length; j++)
test[j] = r.nextInt(10);
customList = new ArrayBasedSwapList<Integer>(test);
customSorter = new QuickSorter<Integer>(customList,
INTEGER_COMPARATOR);
SwapList<Integer> result = customSorter.sort();
if(!result.isSorted(INTEGER_COMPARATOR)) {
System.out.println("Result: " + result.toString());
System.out.println(result.isSorted(INTEGER_COMPARATOR));
}
} while(true);
}
}
按照评论部分的要求-
超类抽象分类器:
我在分区
方法中发现了三个错误或有争议的错误:
- 该方法是
private
,这意味着您没有对其进行单元测试,即使它是您所拥有的最复杂的代码片段之一。
- 您可以通过将其包私有化(一些API,如Guava,提供了一个特殊的
@VisibleForTesting
注释,您可以使用它来明确为什么要这样做),或者通过将其分解为自己的类QuickSorter
委托给它来解决这个问题
- 您的算法假设
i除了@ruakh指出的之外,我还观察到在调用partition()
之后,pivot可以留在数组的任何部分。然而,由于pivot索引中的元素是确定排序的,所以它甚至可以位于列表的最末端
;有条件地调用quicksort()
应该可以解决您的问题。另外,记住@ruakh的答案中已经强调的边缘案例,下面的代码应该可以解决您的所有问题。我已经对这个例程进行了无限次的测试,没有发现任何异常情况
快速排序方法:
private void quicksort(int firstIndex, int lastIndex) {
//System.out.println(indent + "quicksort(" + firstIndex + ", " + lastIndex + ")");
//indent+=" ";
if(firstIndex < lastIndex) {
int p = partition(firstIndex, lastIndex);
//System.out.println(indent + "p = " + p);
if (firstIndex < p - 1)
quicksort(firstIndex, p - 1);
if (p < lastIndex)
quicksort(p, lastIndex);
}
// indent = indent.substring(2);
}
private int partition(int firstIndex, int lastIndex) {
//System.out.println(indent + "Inside partition(" + firstIndex + ", " + lastIndex + ")");
int pivotIndex = (firstIndex + lastIndex) / 2;
//System.out.println(indent + "pivotIndex = " + pivotIndex);
int i = firstIndex;
int j = lastIndex;
while (i <= j) {
while(list.compare(i, pivotIndex, comparator) < 0) {
i++;
}
while(list.compare(j, pivotIndex, comparator) > 0) {
j--;
}
//System.out.println(indent + "Initially: " + list.toString());
//System.out.println(indent + "i = " + i +", pivotIndex = " + pivotIndex + ", j = " + j);
if(i <= j) {
list.swap(i, j);
//System.out.println(indent + "After 1st swap: " + list.toString());
if(i == pivotIndex) {
pivotIndex = j;
//System.out.println(indent + "Pivot was swapped");
}
else if(j == pivotIndex) {
pivotIndex = i;
//System.out.println(indent + "Pivot was swapped");
}
i++;
j--;
//System.out.println(indent + "i = " + i +", pivotIndex = " + pivotIndex + ", j = " + j);
}
}
// list.swap(pivotIndex, i);
//System.out.println(indent + "After 2nd swap: " + list.toString());
//System.out.println(indent + "i = " + i +", pivotIndex = " + pivotIndex + ", j = " + j);
return i;
}
package test;
import java.util.Comparator;
import java.util.Random;
public class Test
{
private static final Comparator<Integer> INTEGER_COMPARATOR = new IntegerComparator();
public static void main(String args[]) {
SwapList<Integer> customList;
AbstractSorter<Integer> customSorter;
do {
Random r = new Random();
int length = r.nextInt(10);
Integer[] test = new Integer[length];
for(int j = 0; j < length; j++)
test[j] = r.nextInt(10);
customList = new ArrayBasedSwapList<Integer>(test);
customSorter = new QuickSorter<Integer>(customList,
INTEGER_COMPARATOR);
SwapList<Integer> result = customSorter.sort();
if(!result.isSorted(INTEGER_COMPARATOR)) {
System.out.println("Result: " + result.toString());
System.out.println(result.isSorted(INTEGER_COMPARATOR));
}
} while(true);
}
}
private void快速排序(int firstIndex,int lastIndex){
//System.out.println(缩进+快速排序(“+firstIndex+”,“+lastIndex+”);
//缩进+=“”;
如果(第一个索引<最后一个索引){
int p=分区(第一个索引,最后一个索引);
//System.out.println(缩进+“p=“+p”);
如果(第一指数
分区方法:private int partition(int firstIndex, int lastIndex) {
//System.out.println(indent + "Inside partition(" + firstIndex + ", " + lastIndex + ")");
int pivotIndex = (firstIndex + lastIndex) / 2;
//System.out.println(indent + "pivotIndex = " + pivotIndex);
int i = firstIndex;
int j = lastIndex;
while (i <= j) {
while(list.compare(i, pivotIndex, comparator) < 0) {
i++;
}
while(list.compare(j, pivotIndex, comparator) > 0) {
j--;
}
//System.out.println(indent + "Initially: " + list.toString());
//System.out.println(indent + "i = " + i +", pivotIndex = " + pivotIndex + ", j = " + j);
if(i <= j) {
list.swap(i, j);
//System.out.println(indent + "After 1st swap: " + list.toString());
if(i == pivotIndex) {
pivotIndex = j;
//System.out.println(indent + "Pivot was swapped");
}
else if(j == pivotIndex) {
pivotIndex = i;
//System.out.println(indent + "Pivot was swapped");
}
i++;
j--;
//System.out.println(indent + "i = " + i +", pivotIndex = " + pivotIndex + ", j = " + j);
}
}
// list.swap(pivotIndex, i);
//System.out.println(indent + "After 2nd swap: " + list.toString());
//System.out.println(indent + "i = " + i +", pivotIndex = " + pivotIndex + ", j = " + j);
return i;
}
package test;
import java.util.Comparator;
import java.util.Random;
public class Test
{
private static final Comparator<Integer> INTEGER_COMPARATOR = new IntegerComparator();
public static void main(String args[]) {
SwapList<Integer> customList;
AbstractSorter<Integer> customSorter;
do {
Random r = new Random();
int length = r.nextInt(10);
Integer[] test = new Integer[length];
for(int j = 0; j < length; j++)
test[j] = r.nextInt(10);
customList = new ArrayBasedSwapList<Integer>(test);
customSorter = new QuickSorter<Integer>(customList,
INTEGER_COMPARATOR);
SwapList<Integer> result = customSorter.sort();
if(!result.isSorted(INTEGER_COMPARATOR)) {
System.out.println("Result: " + result.toString());
System.out.println(result.isSorted(INTEGER_COMPARATOR));
}
} while(true);
}
}