Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中的动态树+;_C++_Arrays_Pointers_Tree - Fatal编程技术网

C++ C+中的动态树+;

C++ C+中的动态树+;,c++,arrays,pointers,tree,C++,Arrays,Pointers,Tree,我想做一棵树,每个节点上都有一些子节点,但我不知道它们的数量。树必须在小内存中编码(无额外数据),每个节点的时间不变。我认为我将用value和children属性(value是int,children是stack)和指向树中每个节点的指针数组来创建类树。我的问题是制作这个数组。如果没有额外的数据(std::vector有时会分配比需要更多的内存)并且每个单元格都有固定的时间,我如何才能做到这一点 一切正常,但我还需要到每个节点的固定时间。我知道将有多少个节点,但我不知道如何制作每个节点的数组。它

我想做一棵树,每个节点上都有一些子节点,但我不知道它们的数量。树必须在小内存中编码(无额外数据),每个节点的时间不变。我认为我将用value和children属性(value是int,children是stack)和指向树中每个节点的指针数组来创建类树。我的问题是制作这个数组。如果没有额外的数据(
std::vector
有时会分配比需要更多的内存)并且每个单元格都有固定的时间,我如何才能做到这一点


一切正常,但我还需要到每个节点的固定时间。我知道将有多少个节点,但我不知道如何制作每个节点的数组。它的工作原理应该是:

数组[n]
A_节点*数组[0]=新的A_节点(16)
A_节点*n=新的A_节点(1)
数组[0]->addChild(n)
数组[1]=n
或:
*(数组+1)=n 只需自己跟踪内存,而不是使用向量:

class Node {
public:
    // In the constructor, initialize your array of children to NULL
    // and the size of your children array to zero
    Node() : mChildren(NULL), mSize(0) {}

    void AddChild(Node* newChild) {
        // allocate space for your new array
        Node** newArray = new Node*[mSize + 1];

        // copy over nodes from old array to new array
        for (int i = 0; i < mSize; i++) {
            newArray[i] = mChildren[i];
        }

        // add in our new child to the end of the array
        newArray[mSize++] = newChild;

        // if there was an old array (null check) free the memory
        if (mChildren) {
            delete [] mChildren;
        }

        // set our children array equal to our new array
        mChildren = newArray;
    }

    Node* AccessChild(size_t index) {
        // make sure it's a valid index and then return
        assert(index < mSize);
        return mChildren[index];
    }

private:
    Node** mChildren;
    int mSize;
};
类节点{
公众:
//在构造函数中,将子数组初始化为NULL
//子数组的大小为零
Node():mChildren(NULL),mSize(0){}
void AddChild(节点*newChild){
//为新阵列分配空间
节点**新数组=新节点*[mSize+1];
//将节点从旧阵列复制到新阵列
对于(int i=0;i
这将没有额外的空间容纳额外的节点,但它需要int的大小来跟踪存储的节点数量。如果没有这个或者没有固定数量的孩子,我看不出有什么办法

请注意,每次需要重新分配向量时,向量的大小都会翻倍,因为这样更有效。尽管上述解决方案在内存方面效率更高,但在性能方面却会受到很大影响,因为它需要为每个子节点添加一个分配,这将需要O(N)个分配来添加N个节点


向量的性能将是O(log(N))分配以添加N个节点,但这个解决方案听起来同样具有您想要的内存效率。

这是一个可能的示例。这不是一个完整的示例解决方案,但我希望您能理解这一点。关键是可以有一个指向节点的双指针,它基本上是指向树节点的指针数组

然后,您可以自己重新分配大小,并在需要时调整到您想要的大小。但是std::vector已经为您做到了这一点,所以没有真正的理由不使用它,除非您想自己控制一切或进行实验,或者正在用C编写一些东西。无论如何,希望这能有所帮助

#include <stdio.h>
#include <stdlib.h>

// The initial buffer length of a node's children
#define BUFFER_LENGTH   5
// How much to multiply with if an addition of a child goes over the buffer
#define MULTIPLIER 2

///Your node class
class A_Node
{
    public:
    A_Node(int value,unsigned int childrenN=0)
    {
        this->value = value;
        this->childrenN = childrenN;

        //allocate BUFFER_LENGTH children for the node at first or childrenN if the childrenN is not initially 0
        if(childrenN != 0)
        {
            this->children = (A_Node**) malloc(sizeof(A_Node*)*childrenN);
            this->bufferLength = childrenN;
        }
        else
        {
            this->children = (A_Node**) malloc(sizeof(A_Node*)*BUFFER_LENGTH);
                        this->bufferLength =BUFFER_LENGTH;
        }
    }

    //in the destructor of a node it would need some special care
    ~A_Node()
    {
        //for every child call the destructor of each child
        for(int i = 0; i < this->childrenN; i++)
        {
            delete this->children[i];
        }

        //and only then free the buffer of the pointers to the children
        free(this->children);
    }

    //adds a child
    void addChild(A_Node* child)
    {
        //reallocate if needed
        if(childrenN >= this->bufferLength)
        {
            realloc(this->children,sizeof(A_Node*)*MULTIPLIER);
        }

        this->children[childrenN] = child;
        this->childrenN++;
    }

    A_Node* getChild(unsigned int i)
    {
        if(i >= this->childrenN)
        {
            return 0;
        }

        return this->children[i];
    }

    void printValue()
    {
        printf("%d\n",this->value);
    }
private:
    int value;
    unsigned int childrenN;
    A_Node** children;
    unsigned int bufferLength;
};

///Your tree class
class A_Tree
{
    public:
        //constructor
        A_Tree(int rootValue)
        {
            root = new A_Node(rootValue);
        }
        //destructor
        ~A_Tree()
        {
            //recursively kills all the nodes due to the destructor of node
            delete root;
        }
        //your root node
        A_Node* root;
};


int main()
{
    A_Tree tree(16);

    tree.root->addChild(new A_Node(42));

    tree.root->printValue();

    (tree.root->getChild(0))->printValue();


    return 0;
}
#包括
#包括
//节点子节点的初始缓冲区长度
#定义缓冲区长度5
//如果子项的加法超过缓冲区,则要乘以多少
#定义乘数2
///您的节点类
A类_节点
{
公众:
A_节点(int值,无符号int childrenN=0)
{
这个->值=值;
此->childrenN=childrenN;
//首先为节点或childrenN(如果childrenN最初不是0)分配缓冲区长度的子节点
if(childrenN!=0)
{
这->children=(A_节点**)malloc(sizeof(A_节点*)*childrenN);
此->缓冲长度=childrenN;
}
其他的
{
这个->子节点=(A_节点**)malloc(sizeof(A_节点*)*缓冲区长度);
该->缓冲区长度=缓冲区长度;
}
}
//在节点的析构函数中,需要特别小心
~A_Node()
{
//对于每个子对象,调用每个子对象的析构函数
对于(int i=0;ichildrenN;i++)
{
删除此->子项[i];
}
//然后才释放指向子对象的指针缓冲区
免费(本->儿童);
}
//添加一个孩子
void addChild(一个节点*子节点)
{
//如果需要,重新分配
如果(childrenN>=此->缓冲区长度)
{
realloc(这个->子节点,sizeof(一个节点*)*乘数);
}
此->儿童[儿童]=儿童;
这->childrenN++;
}
A_Node*getChild(无符号整数i)
{
如果(i>=this->childrenN)
{
返回0;
}
返回此->子项[i];
}
void printValue()
{
printf(“%d\n”,此->值);
}
私人:
int值;
无符号整数儿童;
A_节点**子节点;
无符号整数缓冲长度;
};
///你的树课
A类树
{
公众:
//建造师
A_树(int rootValue)
{
root=新的A_节点(rootValue);
}
//析构函数
~A_树()
{
//由于节点的析构函数,递归地杀死所有节点
删除根;
}
//您的根节点
A_节点*根;
};
int main()
{
一棵树(16);
tree.root->addChild(新的A_节点(42));
root->printValue();
(tree.root->getChild(0))->printValue();
返回0;
}

您需要在该树上执行哪些操作?添加节点,将子节点添加到节点,然后在添加每个节点后,我将创建数组以展平此树(但不是直线)。您所说的“子节点是堆栈”是什么意思?
std::vector
分配更多内存,因为它希望为您节省几个对malloc的不确定的昂贵调用(当您增加vector时)