Я бы выбрал двусвязный список, где каждый узел может быть членом нескольких разных списков одновременно:
struct node
{
struct node *factory_prev;
struct node *factory_next;
struct node *finish_prev;
struct node *finish_next;
struct node *progress_prev;
struct node *progress_next;
};
Первый список связывает все товары, произведенные на этом заводе; база списка с фабричным объектом. Когда на фабрику нападают, вы можете пройти по этому списку, чтобы найти все предметы, которые теперь задерживаются, и вы можете убрать их из других списков.
Второй список связывает все производимые товары, упорядоченные по времени их завершения. Глядя на первый элемент, можно сказать в O (1), закончен ли элемент.
Третий список связывает все элементы, которые передают события прогресса, снова отсортированные по следующему такому событию. Этот механизм очень похож на «финишный» список и теоретически может быть объединен, однако наличие отдельного, более короткого списка позволяет быстрее находить элементы, нуждающиеся в трансляции прогресса.
Поскольку это двусвязные списки, как только у вас есть указатель на узел, вы знаете, как также отсоединить его от всех других списков. Имейте в виду, что в многопоточной программе вам может потребоваться еще какая-то форма блокировки.
Альтернативой было бы перенести предметы, которые были задержаны в то время, когда они обычно производились; однако это довольно сложно получить право на предметы, которые также имеют отчеты о ходе работы.