Распределение памяти в дереве - PullRequest
0 голосов
/ 08 апреля 2019

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

 #define H 7

 class Node{

    public:
         int node_number;
         int depth;
         int value;
         Node* nodes[L];
    public:
         Node new_node(int node_number,int depth,int value);
         void  add_node(Node root_node,Node new_node);
         void  print_node(Node print_node);
};

Чтобы создать узел, мойфункция здесь

Node Node::new_node(int node_number,int depth,int value){
    Node x;
    x.node_number=node_number;
    x.depth=depth;
    x.value=value;
    x.nodes[L]=(Node*) std::malloc(L*sizeof(Node));
    return x; 
 }

и теперь, когда я хочу добавить узлы в узел, как он сам объявлен в классе, я получил ошибку сегментации (сброшено ядро)

void Node::add_node(Node root_node,Node new_node){
    root_node.nodes[0]=&(new_node);
}

Моя основная функция

Node root_node;
root_node=root_node.new_node(10,2,23);

Node x;
x=x.new_node(17,19,7);
root_node.add_node(root_node,x);
root_node.print_node(root_node);

Большое вам спасибо

Ответы [ 2 ]

0 голосов
/ 08 апреля 2019

Хотя уже есть полный ответ , предоставленный PeteBlackerThe3rd , я считаю, что стоит также дать ответ, который не использует какое-либо ручное распределение памяти, так как это часто является предпочтительным способом в C ++.

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

Структура использует std::vector, который имеет (как минимум) два преимущества по сравнению с кодом, приведенным в вопросе. Во-первых, нет необходимости знать максимальное количество дочерних узлов во время компиляции. Если вы хотите исправить это во время компиляции, вы можете легко заменить std::vector на std::array. Во-вторых, нет необходимости вручную освобождать память при уничтожении, так как все это решается std::vector.

#include <iomanip>
#include <vector> 

struct Node
{
  // I expect these data members to be constants
  int const d_nodeNumber;
  int const d_depth;
  int const d_value;

  std::vector<Node> d_childNodes;

  Node() = delete;

  Node(int number, int depth, int value)
  :
    d_nodeNumber (number),
    d_depth      (depth),
    d_value      (value),
    d_childNodes ()
  { }

  /*
   * Note that this function does not ask for a 'depth' argument
   * As the depth of a child is always the depth of its parent + 1
   */

  void addChildNode (int number, int value)
  {
    d_childNodes.emplace_back(number, d_depth + 1, value);
  }

  /*
   * Just an arbitrarily function to generate some output
   */

  void showTreeFromHere() const
  {
    int const n = 1 + 2 * d_depth;

    std::cout << std::setw(n) << ' '
              << std::setw(5) << d_nodeNumber 
              << std::setw(5) << d_depth 
              << std::setw(5) << d_value << std::endl;

    for (Node const &n: d_childNodes)
      n.showTreeFromHere();
  }
};

Структура может быть использована следующим образом:

int main() 
{
  Node root_node(0,0,0);

  // Add two child nodes
  root_node.addChildNode(1,1);
  root_node.addChildNode(2,1);

  // Add six grandchildren
  root_node.d_childNodes[0].addChildNode(3,8);
  root_node.d_childNodes[0].addChildNode(4,8);
  root_node.d_childNodes[0].addChildNode(5,8);
  root_node.d_childNodes[1].addChildNode(6,8);
  root_node.d_childNodes[1].addChildNode(7,8);
  root_node.d_childNodes[1].addChildNode(8,8);

  root_node.showTreeFromHere();
}
0 голосов
/ 08 апреля 2019

Здесь мало проблем.Во-первых, вы фактически не выделяете новую память.Строка в методе new_node

Node x;

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

Тогда в методе add_node есть еще одна проблема:

root_node.nodes[0]=&(new_node);

Эта строка не вызывает метод node_node, она фактически принимает адрес функции.Даже если бы он вызывал метод, он бы возвращал копию объекта в стеке, а не указатель на объект в куче, который вам нужен.

Ваш код не показывает определение LЯ собираюсь предположить, что это макроопределение.Ваш метод new_node должен выглядеть следующим образом: добавьте новое зарезервированное слово, здесь новый объект создается в куче:

Node* Node::new_node(int node_number,int depth,int value){
    Node *x = new Node;
    x->node_number=node_number;
    x->depth=depth;
    x->value=value;
    // x->nodes[L]=(Node*) std::malloc(L*sizeof(Node));
    // not needed if L is a macro and needs correcting if L is a variable
    return x; 
 }

Теперь этот метод возвращает указатель на новый объект в куче.

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

void Node::add_node(Node root_node,Node new_node){
    root_node.nodes[0]=new_node(/* Need to add params here! */);
}

Однако есть гораздо лучший способ сделать то, что вы хотите здесь.Вы должны написать конструктор для класса Node, как показано ниже:

Node::Node(int node_number,int depth,int value)
{
    this->node_number = node_number;
    this->depth = depth;
    this->value = value;
}

Это устраняет необходимость в методе new_node и означает, что ваш метод add_node будет выглядеть следующим образом:

void Node::add_node(Node root_node,Node new_node){
    root_node.nodes[0]=new Node(/* Need to add params here! */);
}

Надеюсь, что этопомогает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...