Для проекта в моем классе Data Structures мне было поручено создать трехмерное дерево диапазонов, где каждое измерение является BST. Я прочитал этот вопрос, но это вопрос Android и причины нашего вопросы кажутся разными, и единственный ответ не был принят.
Стена кода скоро появится. Извините.
Задействованные классы:
Point3D<T>
: Общий класс, содержащий координаты точки.T extends Comparable<T>
иPoint3D
также расширяют егоRangeTree<T>
: универсальный класс, содержащий корень всего дерева и методы для построения и поиска по дереву.
Классов больше, чем эти 2, но они, похоже, не связаны с тем, почему я получаю исключение ConcurrentModificationException (ссылка на CME). Вот что я получаю, когда запускаю свой драйвер:
Read in 10 points //Number of points read in driver, this is okay
5//first median, 10 / 2
2//second median 5 / 2
first[0.082 0.791 0.832 , 0.366 0.136 0.009 ]//correct
second[0.138 0.968 0.391 , 0.414 0.785 0.883 , 0.546 0.044 0.133 ]//correct
merged[0.082 0.791 0.832 , 0.366 0.136 0.009 ]//not correct
first[0.082 0.791 0.832 , 0.366 0.136 0.009 ]//printed again. why?
2//secondHalf being sorted
first[0.415 0.64 0.099 , 0.513 0.612 0.466 ]//correct
second[0.091 0.719 0.772 , 0.199 0.999 0.086 , 0.896 0.835 0.86 ]//correct
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231)
at java.util.ArrayList$SubList.size(ArrayList.java:1040)
at RangeTree.mergeList(RangeTree.java:189)
at RangeTree.sortAscending(RangeTree.java:175)
at RangeTree.sortAscending(RangeTree.java:173)
at RangeTree.build3DTree(RangeTree.java:126)
at RangeTree.build(RangeTree.java:11)
at Main.main(Main.java:35)
Когда вызывается RangeTree.build
(Main.java:35), он принимает List<Point3D<T>>
и передает его в RangeTree.build3DTree
(RangeTree.java:11), который также принимает # оставшихся для построения измерений и аргумент, указывающий, отсортировано ли уже List
. RangeTree.java:126 в этом методе — это строка, в которой я вызываю sortAscending
в build3DTree
.
sortAscending
(это рекурсия) делает то, на что это похоже, сравнивая точки в определенном измерении, начиная с x
(x = 0, y = 1, z = 2), если они равны, он проверяет следующее измерение и т. д. На основе на приведенном выше, он явно работает нормально, за исключением того странного сбоя, когда Line 172
каким-то образом печатается дважды. Ниже приведен код sortAscending
(все строки печати предназначены исключительно для отладки):
private List<Point3D<T>> sortAscending(List<Point3D<T>> pointArr){
if(pointArr.size() <= 3){//minimum sublist size is 3
int median = findMedian(pointArr);
Point3D<T> medianElement = pointArr.get(median);//retrieves coordinate to sort on
int compareLeft = medianElement.compareTo(pointArr.get(median - 1));
if(compareLeft < 0){//determine if median is less than element to its left. There will always be an element to the left
pointArr.add(0, pointArr.remove(median));
medianElement = pointArr.get(median);
}
try{//check median against element to its right. May not be valid if sublist is size 2
int compareRight = medianElement.compareTo(pointArr.get(median + 1));
if(compareRight > 0){
Point3D<T> rightEnd = pointArr.get(median + 1);
Point3D<T> leftEnd = pointArr.get(median - 1);
if(rightEnd.compareTo(leftEnd) < 0)
pointArr.add(0, pointArr.remove(median + 1));
else
pointArr.add(median, pointArr.remove(median + 1));
}
} catch (IndexOutOfBoundsException e){
}
return pointArr;
}
int median = findMedian(pointArr);//returns pointArr.size() / 2
System.out.println(median);//for debugging
List<Point3D<T>> firstHalf = sortAscending(pointArr.subList(0, median));
System.out.println("first" + firstHalf); //prints twice, once when it should, and again after Line 176 prints
List<Point3D<T>> secondHalf = sortAscending(pointArr.subList(median, pointArr.size()));//Line 173
System.out.println("second" + secondHalf);//debugging
List<Point3D<T>> merged = mergeList(firstHalf, secondHalf);//Line 175
System.out.println("merged" + merged);//debugging
return merged;//mergeList(firstHalf, secondHalf);
}
Итак, окончательный источник CME, кажется, находится в mergeList
и не прерывается до вызова со второй половиной данных. mergeList
(итеративный) берет два List<Point3D<T>>
и объединяет их в один список, отсортированный в порядке возрастания, и возвращает его. А именно, он принимает первый аргумент, преобразует его в объединенный список и возвращает его. Код:
private List<Point3D<T>> mergeList(List<Point3D<T>> firstList, List<Point3D<T>> secList){
int sListSize = secList.size();
int fListSize = firstList.size();//Line 188
Point3D<T> firstListElement = firstList.get(fListSize - 1);
Point3D<T> secListElement = secList.get(0);
if(secListElement.compareTo(firstListElement) >= 0){//check to see if secList can be appended to end of firstList e.g. firstList = {1, 2} secList = {3, 4, 5}
firstList.addAll(secList);
return firstList;
}
secListElement = secList.get(secList.size() - 1);
firstListElement = firstList.get(0);
if(secListElement.compareTo(firstListElement) <= 0){//check to see if firstList can be appended to the end of secList e.g. secList = {1, 2} firstList = {3,4,5}
secList.addAll(firstList);
return secList;
}
for(int a = 0; a < secList.size(); a++){//take an element from secList and insert it into firstList
secListElement = secList.get(a);
int minIdx, maxIdx, median = findMedian(firstList);
int mComp = secListElement.compareTo(firstList.get(median));//compare to the median of firstList to choose side to start from
if(mComp < 0){
minIdx = 0;
maxIdx = median;
}
else if(mComp > 0){
minIdx = median;
maxIdx = firstList.size();
}
else{//if mComp is 0, insert it at median index
firstList.add(median, secList.get(a));
continue;
}
for(; minIdx < maxIdx; minIdx++){
firstListElement = firstList.get(minIdx);
int compare = secListElement.compareTo(firstListElement);
if(compare <= 0){
firstList.add(minIdx, secList.get(a));
break;
}
}
}
return firstList;
}
Так почему-то CME приходит, когда я пытаюсь получить доступ к размеру firstList
. Я понятия не имею, почему это происходит. Я вручную проследил каждый шаг своего кода с набором данных (опубликованным ниже), и я не вижу, откуда берется CME. Данные:
10
0.366 0.136 0.009
0.082 0.791 0.832//beautiful 3D points
0.138 0.968 0.391
0.414 0.785 0.883
0.546 0.044 0.133
0.513 0.612 0.466
0.415 0.640 0.099
0.199 0.999 0.086
0.896 0.835 0.860
0.091 0.719 0.772
0.25 0.75 0.25 0.75 0.25 0.75//range queries. Code fails before we get to this
0.75 0.25 0.8 0.1 0.9 0.1
0.95 1.75 0.1 0.01 0.1 0.2
exit//no more queries
sortAscending
. Возможно, мне следует явно указать это в задаче. Я пытался не публиковать кучу кода. - person Ungeheuer   schedule 28.03.2017