Стандартная библиотека не имеет неоднородные структуры данных. У вас есть три подхода: выполните одно из них, используйте однородную структуру, содержащую объекты с тегом union type, или используйте две параллельные структуры.
Минимальный пример гетерогенного списка:
template<class T,class E>
struct node;
template<class T, class E>
struct edge {
node<T, E> *prev, *next;
E data;
};
template<class T, class E>
struct node {
edge<T, E> *prev, *next;
T data;
};
template<class T, class E>
struct fancy_list {
edge<T, E> *head, *tail;
};
struct wagon {
// wagon members
};
struct boundary {
// boundary members
};
int main() {
fancy_list<wagon, boundary> wagons;
}
алгоритмы будут работать в основном так же, как алгоритмы для однородных списков, но вам придется разработать стратегию для борьбы с удалением узлов (Является ли один (вставка до или после существующего края) Скопируйте существующие элементы края в новую или установите состояние по умолчанию?) и т. д. Нет никаких «правильных» или «правильных», лучших "решений без четко определенного варианта использования.
Маркированных реализации объединения std::variant
будут введены в С ++ 17. До тех пор вам придется реализовать свою собственную или быть в зависимости от третьей стороны.
Проблема с этим подходом заключается в том, что структура данных не предусматривает принудительного внедрения инварианта ребер, соседствующих только с узлами и узлами, только соседними ребрами, поэтому в любом случае вам потребуется реализовать собственный набор алгоритмов.
Параллельные структуры для ребер и узлов являются типичным способом реализации графика. Ваш список - это просто частный случай графа, который имеет ровно два ребра для каждого узла.
Вы можете использовать 'std :: list' для достижения этого. –
@ πάνταῥεῖ - При использовании 'std :: list' нет граничных элементов. Я думаю, что они имеют некоторую функцию и не могут быть опущены. – StoryTeller
@StoryTeller Как видно из изображения, граничные элементы представляют собой не что иное, как родовые узлы с двойным узлом. –