У меня древовидная структура, и мой конструктор копирования, кажется, иногда сбрасывает некоторые из моих «листьев».
Базовая структура:
public class Arrow {
ArrayList<Arrow> subArrows;
Interval start;
Interval end;
}
Конструктор копирования:
public Arrow(Arrow other) {
this.start = new Interval(other.start);
this.end = new Interval(other.end);
if (other.subArrows != null) {
this.subArrows = new ArrayList<Arrow>();
for (Arrow sub : other.subArrows) {
this.subArrows.add(new Arrow(sub));
}
} else {
this.subArrows = new ArrayList<Arrow>();
}
}
Я ожидал, что это, по сути, сделает глубокую копию моей древовидной структуры. Вместо этого я иногда обнаруживаю, что один из моих массивов subArrows
пуст. Я не заметил закономерности, кроме того, что они, как правило, находятся на самом нижнем «уровне» моего дерева.
Любые идеи? Я не использовал java некоторое время.
РЕДАКТИРОВАТЬ: несколько человек просили больше кода, так что вот все места, которые касаются подстрелок. Это из довольно большой структуры алгоритма/данных, поэтому было бы неразумно публиковать все это.
Рекурсивно получает все subArrows и возвращает их набор.
Set<Arrow> allSubArrows(Arrow arrow) {
Set<Arrow> arrowSet = new HashSet<Arrow>();
if (arrow.subArrows != null && arrow.subArrows.size() > 0) {
for (Arrow sub : arrow.subArrows) {
arrowSet.addAll(allSubArrows(sub));
}
return arrowSet;
} else {
arrowSet.add(arrow);
return arrowSet;
}
}
Мэти объясняет, что это делает, но subArrows изменены внизу:
void enforceMonotonicity(Arrow arrow) {
boolean changed = false;
if (arrow.end != null && arrow.start != null) {
if (arrow.start.isParallelTo(arrow.end)) {
//either left to right or bottom to top
if (arrow.start.isVertical()) {
//left interval pointing to right interval
if (arrow.start.startGraph.y > arrow.end.startGraph.y) {
arrow.end.startGraph.y = arrow.start.startGraph.y;
changed = true;
}
if (arrow.end.endGraph.y < arrow.start.endGraph.y) {
arrow.start.endGraph.y = arrow.end.endGraph.y;
changed = true;
}
} else {
//bottom interval pointing to top interval
if (arrow.start.startGraph.x > arrow.end.startGraph.x) {
arrow.end.startGraph.x = arrow.start.startGraph.x;
changed = true;
}
if (arrow.end.endGraph.x < arrow.start.endGraph.x) {
arrow.start.endGraph.x = arrow.end.endGraph.x;
changed = true;
}
}
}
}
if (changed) {
//check to make sure SOMETHING is still reachable, if not arrow = null
if (arrow.start.isVertical()) {
if (arrow.start.startGraph.y >= arrow.start.endGraph.y ||
arrow.end.startGraph.y >= arrow.end.endGraph.y) {
arrow = null;
}
} else {
if (arrow.start.startGraph.x >= arrow.start.endGraph.x ||
arrow.end.startGraph.x >= arrow.end.endGraph.x) {
arrow = null;
}
}
//if we changed the outer arrows, we need to recursively change the subarrows
if (arrow != null && arrow.subArrows != null && arrow.subArrows.size() > 0) {
for (Arrow sub : arrow.subArrows) {
enforceMonotonicity(sub);
}
}
}
}
Часть алгоритма слияния:
HashSet<Arrow> mergeCells(Set<Arrow> first, Set<Arrow> second) {
HashSet<Arrow> mergedCell = new HashSet<Arrow>();
//loop through arrows in adjacent cells and find the ones that connect
for (Arrow topArrow : first) {
for (Arrow bottomArrow : second) {
if(topArrow.start.intersects(bottomArrow.end)) {
//merge arrows
Interval middle = topArrow.start.intersection(bottomArrow.end);
Arrow newArrow = new Arrow();
if (middle != null) {
//if they connect, we copy the two arrows, modify their connection,
//create a new arrow with the constituents as subarrows, and add that to the mergedcell
//after the mergedcell is created, we can delete the base arrows
Arrow topCopy = new Arrow(topArrow);
topCopy.start = middle;
Arrow bottomCopy = new Arrow(bottomArrow);
bottomCopy.end = middle;
newArrow.subArrows.add(topCopy);
newArrow.subArrows.add(bottomCopy);
newArrow.start = bottomCopy.start;
newArrow.end = topCopy.end;
//if end and middle are parallel, we need to project monotonicity
//monotonicity is already enforced within a single cell
//and enforcemonotonicity knows whether or not start and end are parallel
enforceMonotonicity(newArrow);
}
//enforceMonotonicity could null out the new arrow
if (newArrow != null && !newArrow.isNull()) {
mergedCell.add(newArrow);
}
}
}
}
//keep the originals in case they can connect later on
//(hashset doesn't allow duplicates, so no need to worry here)
mergedCell.addAll(first);
mergedCell.addAll(second);
return mergedCell;
}
this.subArrows = new ArrayList<Arrow>();
происходит в обоих случаях - он может появиться за пределамиif
. - person OldCurmudgeon   schedule 11.01.2013subArrows
только один раз передif
? - person Diego Basch   schedule 11.01.2013new Arrow(sub)
тихо выйти из строя? т.е. возможно, он выдает исключение, которое перехватывается и отбрасывается в другом месте. В этом отношении -new Interval
также может иметь эту проблему (что объясняет, почему массив пуст). - person OldCurmudgeon   schedule 11.01.2013