将间隔拆分为数组,使每个数组中的元素不重叠

时间:2013-12-04 12:37:56

标签: ios algorithm sorting

我正在尝试对一组对象进行排序。每个对象都有一个开始和结束时间。开始和结束可以重叠,因此,应该显示在不同的行中。 数组看起来像这样:

 event1, from 08:00, till 09:00
 event2, from 08:30, till 09:30
 event3, from 09:00, till 10:30
 event4, from 10:00, till 10:30
 event5, from 12:00, till 14:00

我想以图形方式显示它们:

|08:00-09:00|         |10:00-11:00|           |12:00-14:00|
      |08:30-09:30|
            |09:00  -  10:30|

我正在尝试对它们进行排序,以便结果是每一行都是一个数组,但我找不到正确的方法。

最好的方法是什么?

编辑: thx所有建议:-)以下代码完成工作

NSMutableDictionary *allLines = [[NSMutableDictionary alloc] init];
NSMutableArray *firstLine = [[NSMutableArray alloc] init];
[firstLine addObject:[self.tasks objectAtIndex:0]];
[allLines setObject:firstLine forKey:@"1"];

for(int i = 1; i < [self.tasks count]; i++) {
    if (i == [self.tasks count]) {
        break;
    }
    Task *nextTask = [self.tasks objectAtIndex:i];
    for (int j = 1; j <= [allLines count]; j++) {
        NSMutableArray *theArray = [allLines objectForKey:[NSString stringWithFormat:@"%i",j]];
        NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"timerTillHour" ascending:YES];
        NSArray *sortDescriptors1 = [NSArray arrayWithObject:sortDescriptor1];
        NSArray *sortedArray1 = [theArray sortedArrayUsingDescriptors:sortDescriptors1];

        Task *theTask = [sortedArray1 lastObject];
        if (theTask.timerTillHour+30 > nextTask.timerFromHour) {
            if (j == [allLines count]) {
                NSMutableArray *nextLine = [[NSMutableArray alloc] init];
                [nextLine addObject:nextTask];
                [allLines setObject:nextLine forKey:[NSString stringWithFormat:@"%i",j+1]];
                break;
            } else {
                continue;
            }
        } else {
            [theArray addObject:nextTask];
            break;
        }
    }
}

这导致以下结果:

enter image description here

5 个答案:

答案 0 :(得分:2)

嗯,这就是我要做的事情:

对于每个对象,您需要指定一个显示此项目的行(可能是一行对应的行)。您只需要为每个项目指定一行,您可以在贪婪的样式算法中执行此操作

伪语言

 for each item
      line = 0
      while item.overlap( last_element(line) )
          line = line+1
      item.line = line

我们的想法是为每个项目分配与其兼容的最低行。 您需要以某种方式存储与行(last_element(line))关联的最后一个元素。 分配item.line = line时,您需要更新line的最后一个元素。您可以使用单维数组来实现这一目标,因为line很容易受到项目数量的限制。

这提供了有效的配置。如果你想让配置最小化某个指标(比如行数),你将无法使用贪婪算法。 Dynamic programming可能是有序的。

答案 1 :(得分:0)

这是一个快速的算法:

您需要一个二维数组或一个包含数组或新数据结构的字典来保存二维值

create a model with startTime and endTime.


for each event say e
    if array is empty add event
   else{
          read endTime of last object from the array say l
          if e.startTime < l.endTime
                add e above array as a column
          else
                add e to new row

   }
next 

答案 2 :(得分:0)

你有一组对象(间隔),其中一些与其他对象相冲突(即间隔相交)。如果相应的间隔相交,则考虑图中节点的间隔和两个节点之间存在的边。

因此,问题减少到用不同颜色表示不同线条的图形着色 在输出中。

答案 3 :(得分:0)

如果要最小化使用的行数,可以实现上面提到的动态编程解决方案,也可以使用图论中的算法。

您描述的问题基本上是DAG的vertex-disjoint path cover problem版本。

维基百科有一个基于Bipartite Graph属性的解决方案here。另外,请阅读Airline Scheduling的最后一段,这基本上就是您的问题。

答案 4 :(得分:0)

这可以通过扫描线算法完成(例如,参见http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=lineSweep)。基本上,当新的间隔开始时,您在具有最小索引的行中呈现间隔,而不是由扫描线算法的活动集中的任何间隔占用。

扫描线算法(伪代码):

struct Interval { double start; double end; }
struct Event { Interval* interval; bool isStart; /* otherwise an end event */ }

vector<Event> events = all start / end events of your interval list
sort(events); // sort all interval points. If they are equal, give
              // priority to start events. This will allow some space
              // between two boxes at the same row.

set<Interval> active_set;
for (Event e : events):
    if (isStartEvent(e)):
        active_set.add(e.interval);
        decide where to draw the interval
    else:
        active_set.remove(e.interval);