我有一个快速排序算法来对ArrayLists进行排序。由于我使用的是ArrayLists而不是Arrays,因此与the traditional way相比,我不得不修改/添加部分代码。
除了一件小事之外,一切都按预期工作:当我有多个具有相同排序值的对象时,ArrayList未正确排序。
所以,首先,这是我的代码:
public class Sort
{
... // Other sorting classes that always have an unique sorting-value anyway, so are working fine
// The following sorting class can have double sorting-values, and here the sorting goes wrong
public static class OPI{
public static ArrayList<OrderedProductItem> opisByProductId;
public static void sortOrderedProductItems(ArrayList<OrderedProductItem> orderedProductItems){
opisByProductId = new ArrayList<OrderedProductItem>();
if(orderedProductItems != null && orderedProductItems.size() > 0){
// Since Java automatically creates a pointer behind the scenes,
// we need to make a new ArrayList and fill them with the values
for(OrderedProductItem opi : orderedProductItems)
opisByProductId.add(opi);
quicksortOpisByProductId(0, opisByProductId.size() - 1);
}
}
private static void quicksortOpisByProductId(int low, int high){
int i = low, j = high;
// Get the middle element from the middle of the list
int middle = opisByProductId.get(low + (high - low) / 2).getProductId();
// Divide into two lists
while(i <= j){
// If the current value from the left list is smaller than the middle
// element, then get the next element from the left list
while(opisByProductId.get(i).getProductId() < middle){
i++;
if(i > j){
i = j;
break;
}
}
// If the current value from the right list is larger than the middle
// element, then get the next element from the right list
while(opisByProductId.get(j).getProductId() > middle){
j--;
if(j < i){
j = i;
break;
}
}
// If we have found a value in the left list which is larger than
// the middle element and if we have found a value in the right list
// which is smaller than the middle element, then we exchange the values
// PS: It might happen that the same values swap places
if(i < j){
OrderedProductItem temp = opisByProductId.get(i);
opisByProductId.set(i, opisByProductId.get(j));
opisByProductId.set(j, temp);
}
if(i <= j){
i++;
j--;
}
}
// Recursion
if(low < j)
quicksortOpisByProductId(low, j);
if(i < high)
quicksortOpisByProductId(i, high);
}
}
}
示例列表:
在排序算法之前:
position ProductId
0 12
1 12
2 54
3 54
4 12
5 4
6 4
7 4
排序算法后:
position ProductId
0 4
1 4
2 12
3 12
4 12
5 4
6 54
7 54
答案 0 :(得分:0)
好的我调试了你的程序,在这里发现了我的
你的高位继续下降从未回升过。
if(low < j)
quicksortOpisByProductId(low, j);
if(i < high)
quicksortOpisByProductId(i, high);
我将此更改为
if(low < j)
quicksortOpisByProductId(low, j);
if(i < high)
quicksortOpisByProductId(i, opisByProductId.size() - 1);
它有效
未完成您的程序更改了阵列7次
添加此项后,它会再循环3次,最多需要10次。
答案 1 :(得分:0)
好的,我弄清楚了我的错误。在我有的while循环中
// If the current value from the left list is smaller than the middle
// element, then get the next element from the left list
while(opisByProductId.get(i).getProductId() < middle){
i++;
if(i > j){
i = j;
break;
}
}
// If the current value from the right list is larger than the middle
// element, then get the next element from the right list
while(opisByProductId.get(j).getProductId() > middle){
j--;
if(j < i){
j = i;
break;
}
}
我在if语句中使用j和i。相反,我现在使用以下内容修复我的问题:
// If the current value from the left list is smaller than the middle
// element, then get the next element from the left list
while(opisByProductId.get(i).getProductId() < middle){
i++;
if(i > high){ // <- high instead of j
i = high; // <- high instead of j
break;
}
}
// If the current value from the right list is larger than the middle
// element, then get the next element from the right list
while(opisByProductId.get(j).getProductId() > middle){
j--;
if(j < low){ // <- low instead of i
j = low; // <- low instead of i
break;
}
}
编辑:
使用@ DaveP的测试数据创建了一个UnitTest,并且成功了:
package business;
import java.util.ArrayList;
import junit.framework.Assert;
import org.junit.Test;
import viewmodels.OrderedProductItem;
public class SUnitTest
{
... // Other UnitTests
@Test
public void testDoubleSorting(){
// Arrange
// Could be with any of them, but we do it with the OrderedProductItems,
// since they can contain doubles
ArrayList<OrderedProductItem> opis = new ArrayList<OrderedProductItem>();
int[] unsortedIds = new int[]{
12, 12, 54, 54, 12, 4, 4, 4, 7, 76, 45, 44, 1, 2, 34, 5, 4
};
// Sorted array of the exact same ID's for comparison
int[] sortedIds = new int[]{
1, 2, 4, 4, 4, 4, 5, 7, 12, 12, 12, 34, 44, 45, 54, 54, 76
};
for(int i = 0; i < unsortedIds.length; i++)
// OrderedProductItem uses setProductId in its Constructor
opis.add(new OrderedProductItem(unsortedIds[i]));
// Invoke
Sort.OPI.sortOrderedProductItems(opis);
ArrayList<OrderedProductItem> resultOpis = Sort.OPI.opisByProductId;
// Assert
Assert.assertNotNull("resultOpis should not be null", resultOpis);
Assert.assertEquals("resultOpis' size should equal the unsortedIds' size", unsortedIds.length, resultOpis.size());
for(int i = 0; i < sortedIds.length; i++){
Assert.assertNotNull("The OrderedProductItem at " + String.valueOf(i) + " should not be null", resultOpis.get(i));
Assert.assertEquals("The OrderedProductItem's ProductId at " + String.valueOf(i) + " should be " + String.valueOf(sortedIds[i]), sortedIds[i], resultOpis.get(i).getProductId());
}
}
}