树中的内存分配

时间:2019-04-08 12:36:04

标签: c++ tree

大家好,我希望您过得愉快,我在为树分配内存时遇到了一些问题,我认为这更容易解释和理解。

 #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 :(得分:0)

There are few problems here. Firstly you're not actually allocating any new memory. The line in the new_node method

Node x;

is a local variable so it will be destroyed when the method completes, the method then returns a copy of this object on the stack.

Then in the add_node method there is another problem:

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

This line doesn't call the node_node method, it actually takes the address of the function. Even if it did call the method it would be returning a copy of the object on the stack not a pointer to an object on the heap which is what you need.

Your code doesn't show the definition of L, I'm going to assume that it is a macro definition. Your new_node method should look like this, node the new reserved word, this is where the new object is created on the heap:

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; 
 }

Now this method returns a pointer to a new object on the heap.

Your add_node method will then look like this:

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

However there is a much better way of doing what you want here. You should write a constructor for the Node class like below:

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

This removes the need for the new_node method and means your add_node method will look like this:

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

Hope this helps.

答案 1 :(得分:0)

尽管complete answer已经提供了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();
}