基于优先级的时间线Event冲突消解算法循环逻辑如何设计?
区间冲突消解算法实现方案
你原来的相邻两两遍历逻辑缺了核心的「高优先级事件被截断后的剩余部分留存」逻辑,刚好你的场景有同一时间最多2个事件重叠的限制,用扫描线算法可以完美覆盖所有规则,实现复杂度很低,不需要处理冲突组或笛卡尔积。
核心思路
把所有事件的开始、结束时间拆成独立的时间点,按时间顺序扫描,维护当前时间段内的激活事件,每次时间点变化时,取当前激活事件中优先级最高的生成对应区间的结果即可。
具体实现步骤
前置准备
所有事件都包含name、start_time、end_time、priority四个属性,优先级数值大小代表的优先级高低可自行定义,只要能正常比较大小即可。
- 生成时间点集合
对每个事件生成两个时间节点:- 开始节点:
(start_time, 0, event),第二个参数是排序权重,保证同时间下结束节点先处理 - 结束节点:
(end_time, 1, event)
- 开始节点:
- 时间点排序
排序规则:首先按时间升序排列,时间相同的情况下结束节点排在开始节点前面(避免相邻事件的边界判定为重叠) - 遍历扫描生成结果
初始化变量:- 结果列表
result = [] - 当前激活事件集合
active = set()(最多只会有2个元素) - 上一个时间点
prev_time = None - 事件命名计数器
name_counter = defaultdict(int),用来给同一事件拆分出的多段加NEW后缀
遍历每个排序后的时间节点:
for curr_time, op_type, event in sorted_time_points: # 上一个时间点到当前时间点有有效区间,且有激活事件 if prev_time is not None and curr_time > prev_time and active: # 取激活事件里优先级最高的 high_prio = max(active, key=lambda x: x.priority) # 生成事件名 if name_counter[high_prio.name] == 0: curr_name = high_prio.name else: curr_name = f"{high_prio.name}-NEW{name_counter[high_prio.name]}" name_counter[high_prio.name] += 1 # 加入结果 result.append(Event(curr_name, prev_time, curr_time)) # 处理当前时间点的操作 if op_type == 0: # 开始事件,加入激活集合 active.add(event) else: # 结束事件,从激活集合移除 active.remove(event) # 更新上一个时间点 prev_time = curr_time - 结果列表
场景验证
用你给出的示例测试,事件按优先级从高到低为:B > A > E > D > C,扫描过程完全符合你给出的4条冲突规则,最终输出和你提供的预期结果完全一致。
内容的提问来源于stack exchange,提问作者gene b.
相关产品推荐
相关产品推荐

