简体   繁体   English

如何在不使用动态内存分配的情况下创建基于指针的二叉树?

[英]How do you create a pointer-based binary tree without using dynamic memory allocation?

Some C++ programmers say that dynamic memory allocation is bad and should be avoided whenever possible. 一些C ++程序员说动态内存分配是不好的,应尽可能避免。 I tried making a binary tree data structure without using dynamic memory allocation, and it doesn't work. 我尝试在不使用动态内存分配的情况下建立二叉树数据结构,但它不起作用。 Here's what I tried: 这是我尝试过的:

struct BTNode {
    BTNode *left = 0, *right = 0;
    int data;

    BTNode(int d_) { data = d_; }

    void insert(int d_) {
        BTNode n(d_);
        if (d_ <= data)
            if (left == 0) left = &n;
            else left->insert(d_);
        else 
            if (right == 0) right = &n;
            else right->insert(d_);
    }
}

And then doing this in main... 然后主要这样做

BTNode root(8);
root.insert(9);
root.insert(10);
cout << root.right->right->data;

results in a segfault, because the BTNode containing the data went out of scope a long time ago. 导致段错误,因为包含数据的BTNode很久以前就超出了范围。

My question is, how is one supposed to structure a pointer-based binary tree like this without the use of new and delete ? 我的问题是,在不使用newdelete情况下,如何构造这样的基于指针的二叉树?

The short answer is: you pretty much can't. 简短的答案是:您几乎不能。

The only possible way is for the entire tree to be in either automatic, or global scope, and constructed manually: 唯一可能的方法是使整个树处于自动范围或全局范围内,并手动构建:

BTNode root;
BTNode left, right;

root.left=&left;
root.right=&right;

But, either the whole thing gets destroyed, when the automatic scope is left, or you now have a bunch of ugly globals. 但是,要么保留整个自动范围就破坏了整个事情,要么现在有了一堆丑陋的全局变量。

There's nothing wrong with dynamic scope, and dynamic memory allocation; 动态范围和动态内存分配没有任何问题。 provided that it's used correctly. 只要正确使用即可。

You can have all your nodes in a single std::array<> . 您可以将所有节点都放在一个std::array<> They can freely point to each other an when you release your array, all your nodes are safely released as well. 它们可以相互指向对方,当您释放阵列时,所有节点也将安全释放。 You just have to make sure to know which elements in your array have already been used. 您只需要确保知道数组中的哪些元素已被使用即可。

Any way, please only implement your own trees and similar containers for educational reasons, or if you have very, very, very good reasons not to use the ones provided by the standard library. 无论如何,请仅出于教育原因而实现自己的树和类似的容器,或者如果您有非常非常非常好的理由不使用标准库提供的树和类似的容器。 In the latter case, mimic the standard interface as closely as possible in order to enable standard algorithms, range based for-loops, and easily understandable code for other C++ developers. 在后一种情况下,请尽可能地模仿标准接口,以启用标准算法,基于范围的for循环以及其他C ++开发人员易于理解的代码。

The insert method is allocating the BTNode object on the stack, that means the object's memory is invalid once the insert function returns. insert方法是在堆栈上分配BTNode对象,这意味着一旦insert函数返回,该对象的内存将无效。

You could do 你可以做

       BTNode newObj( 9 ) 
       root.insert( newObj );

You would also have to modify the insert method to 您还必须将insert方法修改为

       void insert(BTNode &node) { ...

in this case newObj object remains in scope until you leave your main function. 在这种情况下,newObj对象将保留在作用域中,直到您离开主函数为止。 Even better you can make it of static scope, then it will be around for the duration of the program. 更好的是,可以将其设置为静态范围,然后在程序运行期间一直存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM