2017-01-27 3 views
1

У меня есть класс двоичного поиска, и я хочу написать функцию для удаления специального узла, но я не знаю, как это сделать. базовый класс:Удаление в дереве bst

class Node { 
    friend class Tree; 
private: 
    long long rep; 
    Node *left, *right; 
    string data; 
public: 
    Node(string d) 
     : data(d), left(NULL), right(NULL), rep(1) {} 
}; 

class Tree { 
private: 
    Node *root; 
public: 
    void delete_node(Node *cur , string s); 
    void delete_node_helper(string s); 
}; 
+0

Лучшим способом является использование умного указателя как 'std :: unique_ptr ' вместо 'Node *'. – Jarod42

+0

Как именно вы хотите удалить узел? Вы хотите заменить его заполнителем или удалить? Должна ли балансировка дерева после этого удаления? Какова ожидаемая асимптотическая сложность? – alexeykuzmin0

+0

А что такое 'rep'? – alexeykuzmin0

ответ

0

Там вы 3 части в удалении узла из бинарного дерева поиска:

  1. найти узел для удаления.
  2. Удалить узел (свободная память и т. Д.).
  3. Объединить детей удаленного узла.

В вашем конкретном примере кода, я бы сказал, что ищет узел должен нести ответственность void delete_node_helper(string s);, удаление узла должна быть ответственность void delete_node(Node *cur, string s);, и объединение детей должны нести ответственность за вновь созданной функция.

Учитывая, что алгоритмы первых двух частей довольно просты, позвольте мне подробно объяснить только третий.

Чтобы слить два BST s (из которых мы знаем, какой из них оставлен, а какой правильный), мы должны решить, кто будет дочерним и, если необходимо, выполнить рекурсивное слияние. Код выглядит так:

Node* merge(Node* left, Node* right) { 
    if (left == nullptr) { 
     return right; 
    } 
    if (right == nullptr) { 
     return left; 
    } 
    if (rand() & 1) {        // <- chose parent 
     left->right = merge(left->right, right); 
     return left; 
    } 
    right->left = merge(left, right->left); 
    return right; 
} 

На отмеченной строке мы фактически принимаем решение о том, какой узел будет родителем. В этом конкретном примере результат случайный, но любая другая стратегия может быть реализована. Например, вы можете хранить высоты (или размеры) во всех узлах вашего дерева и делать меньший корень дерева корней большего корня дерева.

+0

Прокомментируйте, если что-то неясно в частях 1 и 2. – alexeykuzmin0

+0

Пожалуйста, не предлагайте использовать 'rand()' в чем-то подобном. Во всяком случае, это вредит производительности, потому что он должен выполнять вызов функции и условную ветвь без какого-либо реального выигрыша. Ваше замечание об использовании высоты поддерева намного лучше! –

+0

@ G.Sliepen Что вы рекомендуете использовать вместо 'rand()' в случае, если мы не сможем изменить древовидную структуру (что означает, что она не хранит высоту или размер или что-то еще)? Я лично не знаю никаких лучших решений. – alexeykuzmin0

Смежные вопросы