У меня есть класс Tree
, который я хотел бы расширить в более специализированные структуры данных, такие как Order_tree
и Interval_tree
. Эти дополнения требуют дополнений к Node
, таких как информация о размере и незначительные изменения некоторых алгоритмов.Усиление структуры данных без потери памяти
Я хотел бы знать, как наилучшим образом реализовать дополнения в C++ с точки зрения производительности, удобочитаемости и ремонтопригодности. Деревья не должны использоваться полиморфно. До сих пор я пытался публично наследовать Tree
, а затем перегружать базовые методы. (Прошу прощения за то, что новичок в объектно-ориентированном программировании)
template <typename T>
class Tree {
protected:
enum class Color : char {BLACK = 0, RED = 1};
struct Node {
T key;
Node *parent, *left, *right;
Color color;
Node() : color{Color::BLACK} {} // sentinel construction
Node(T val, Color col = Color::RED) : key{val}, parent{nil}, left{nil}, right{nil}, color{col} {}
};
using NP = typename Tree::Node*;
NP root {nil};
// nil sentinel
static NP nil;
// core utility algorithms...
};
template <typename T>
typename Tree<T>::NP Tree<T>::nil {new Node{}};
Заказать дерево
template <typename T>
class Order_tree : public Tree<T> {
using Color = typename Tree<T>::Color;
using Tree<T>::Tree; // inherit constructors
struct Order_node {
T key;
Order_node *parent, *left, *right;
size_t size; // # of descendent nodes including itself = left->size + right->size + 1
Color color;
Order_node() : size{0}, color{Color::BLACK} {} // sentinel construction
Order_node(T val, Color col = Color::RED) : key{val}, parent{nil}, left{nil}, right{nil}, size{1}, color{col} {}
};
using NP = typename Order_tree::Order_node*;
NP root {nil};
static NP nil;
// overloading on only the methods that need changing
};
template <typename T>
typename Order_tree<T>::NP Order_tree<T>::nil {new Order_node{}};
Однако это не ведет себя должным образом, так как теперь у меня есть 2 корня и 2 Nils, со всей базой методы, работающие с базовым корнем, и с Tree<T>::NP
, а не Order_tree::NP
, поэтому атрибут размера Order_node
не может быть использован.
Один из способов заключается в том, чтобы скопировать код, который очень не подлежит контролю. Другой способ, по-моему, состоит в шаблоне Tree на T, а также в NP, так что Order_tree
является псевдонимом using Order_tree = Tree<Order_node>
и специализирует дерево на узле.
Имеет смысл иметь параметр шаблона 'T' для ваших различных классов' tree' - структуру, которую они должны хранить в каждом узле, включая то, что вы сейчас рассматриваете как данные «значение» и «увеличение». Если вы хотите, чтобы определенная часть типа данных 'T' действовала как ключ, вы можете потребовать, чтобы это поле называлось' key', что существует 'typedef' для' key_type; 'или что-то еще, что поддерживает ваше предполагаемое использование клиента ; или, альтернативно, у вас может быть второй параметр шаблона специально для ключа, как это сделано для 'std :: map'. –
Будет ли это дополнительный уровень косвенности, хотя (с точки зрения удобочитаемости и производительности)? (для доступа к ключу вам нужно сказать «node-> data-> key», предполагая, что полезная нагрузка узла - это «данные T», где данные, как вы предполагали, будут структурой, удерживающей хотя бы ключ. – LemonPi