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

class Node {
private:
    Node *parent;
    std::unique_ptr<Node> left;
    std::unique_ptr<Node> right;
public:
    Node(Node* _left, Node* _right, Node* _parent);
};

Node::Node(Node* _left, Node* _right, Node* _parent) {
    parent = &_parent;

    //this is where the problem starts
}

Я не понимаю, как указать на новый узел, который может иметь дерево, которое я хочу подключить. Если я использую make_unique, я верю, что это создаст новый узел вместо сохранения дерева.

Я могу быть совершенно неправ в этом, так как я только что выучил умные указатели около 4 дней назад (Реально достаточно времени, чтобы чему-то научиться).

2
Dogunbound hounds 7 Сен 2017 в 23:03

3 ответа

Лучший ответ

Прежде всего, возможно пустое дерево, и построенный узел по умолчанию будет хорошо вписываться. Родительская ссылка будет известна во время присоединения узла, поэтому родительский узел дочернего узла должен обновляться после того, как узел будет задан как левый или правый дочерний элемент текущего дерева.

Это может быть хорошей идеей получить unique_ptr, поскольку вы переходите во владение указателем, который вы получаете. Вот пример реализации:

class Node {
private:
  Node *parent = nullptr;
  std::unique_ptr<Node> m_left;
  std::unique_ptr<Node> m_right;

public:

  void left(std::unique_ptr<Node> child) {
    m_left = std::move(child);
    m_left->parent = this;
  }

  void right(std::unique_ptr<Node> child) {
    m_right = std::move(child);
    m_right->parent = this;
  }
};

Вы будете использовать его следующим образом:

int main()
{
  auto tree = std::make_unique<Node>();
  auto subtree = std::make_unique<Node>();

  subtree->right(std::make_unique<Node>());
  tree->right(std::make_unique<Node>());
  tree->left(std::move(subtree));
  return 0;
}

Я довольно плохо знаком с unique_ptr, надеюсь, кто-нибудь еще исправит меня. Кстати, не используйте имена, которые начинаются с _ для ваших идентификаторов, они зарезервированы.

5
Error - Syntactical Remorse 7 Сен 2017 в 21:29

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

struct Node
{
    Node(std::unique_ptr<Node> _parent = nullptr, 
std::unique_ptr<Node> _left = nullptr, std::unique_ptr<Node> _right = nullptr) : parent(_parent), left(_left), right(_right) {}

    std::unique_ptr<Node> parent;
    std::unique_ptr<Node> left;
    std::unique_ptr<Node> right;

};

Кто-нибудь, пожалуйста, поправьте меня, если я ошибаюсь.

0
Sailanarmo 7 Сен 2017 в 20:17

Я не думаю, что вы можете использовать:

Node(Node _left, Node _right, Node _parent);

Это не позволит строить дерево узел за узлом. Вместо этого используйте:

Node(Node* _left, Node* _right, Node* _parent);

Таким образом, вы можете создать первый узел, используя:

Node firstNode(nullptr, nullptr, nullptr);

Оттуда вы можете строить другие узлы.

Чтобы построить простое дерево с тремя узлами, как показано ниже

            N1
           /  \
         N2    N3

Вы можете использовать:

Node* N1 = new Node(nullptr, nullptr, nullptr);
Node* N2 = new Node(nullptr, nullptr, N1);
Node* N3 = new Node(nullptr, nullptr, N1);

N1->left = N2;  // Use the equivalent member function.
N1->right = N3;
2
R Sahu 7 Сен 2017 в 20:11