這裏是一個可能解決方案的高級草圖(使用星期幾整數而不是全部日期)。此接口:
public interface IEvent {
public abstract int getFirst(); // first day of event
public abstract int getLast(); // last day of event
public abstract int getLength(); // total number of days
public abstract char getLabel(); // one-char identifier
// true if this and that have NO days in common
public abstract boolean isCompatible(IEvent that);
// true if this is is compatible with all events
public abstract boolean isCompatibleWith(Collection<IEvent> events);
}
必須實現使用下面的方法layout
表達的算法。
此外,具體的類必須實現Comparable
創建一個自然順序,其中較長的事件先於較短的事件。 (下面我對演示示例實現使用降長度,然後上升開始日期,然後上升標籤的順序。)
的layout
方法採用IEvent
實例的集合,並返回一個Map
指派到每一行中的呈現可以在該行中顯示的一組事件。
public Map<Integer,Set<IEvent>> layout(Collection<IEvent> events) {
Set<IEvent> remainingEvents = new TreeSet<IEvent>(events);
Map<Integer,Set<IEvent>> result = new TreeMap<Integer,Set<IEvent>>();
int day = 0;
while (0 < remainingEvents.size()) {
Set<IEvent> dayEvents = new TreeSet<IEvent>();
for(IEvent e : remainingEvents) {
if (e.isCompatibleWith(dayEvents)) {
dayEvents.add(e);
}
}
remainingEvents.removeAll(dayEvents);
result.put(day, dayEvents);
++day;
}
return result;
}
每一行是通過選擇剩餘的最長事件和逐步選擇所有其他事件(在上面所描述的順序),其與當前行先前選擇的事件兼容組成。其效果是所有事件儘可能向上「浮動」而不會發生碰撞。
以下演示顯示了您的問題中的兩種情況,以及隨機創建的一組事件。
Event collection:
x(1):4
b(5):2..6
y(1):5
a(2):1..2
z(1):6
Result of layout:
0 -> {b(5):2..6}
1 -> {a(2):1..2, x(1):4, y(1):5, z(1):6}
Visual presentation:
bbbbb
aa xyz
Event collection:
x(1):1
b(3):2..4
a(2):1..2
c(2):4..5
y(1):5
Result of layout:
0 -> {b(3):2..4, x(1):1, y(1):5}
1 -> {a(2):1..2, c(2):4..5}
Visual presentation:
xbbby
aa cc
Event collection:
f(2):1..2
h(2):1..2
d(4):1..4
e(4):2..5
c(1):6
a(2):5..6
g(4):2..5
b(2):0..1
Result of layout:
0 -> {d(4):1..4, a(2):5..6}
1 -> {e(4):2..5, b(2):0..1, c(1):6}
2 -> {g(4):2..5}
3 -> {f(2):1..2}
4 -> {h(2):1..2}
Visual presentation:
ddddaa
bbeeeec
gggg
ff
hh
我不太明白例1&2和3&4的區別。例如5--我沒有看到任何其他的方式來安排將使用較少的垂直空間的事件。因爲無論如何b/c/d/e中沒有兩個可以在同一條線上,所以至少需要4條線。 – 2008-12-30 14:23:28
你是對的,我的意圖根本不清楚。我只是做了一些編輯,希望能讓它更清晰。 – 2008-12-30 14:30:32