在学习C时,我更关注内存分配,我们在大学里,基本上是用这段代码来构建一个二叉树的,每次在for循环中,都会创建一个指针,只有这样,我们才能把每个子树和它的子树的地址赋给节点,但是我们已经创建了超过10个指针了,对吗?,我们可以只拥有一个指针,然后不断更新它吗?就像递归的实现一样,主指针只被更新然后返回。
typedef struct tr {
int data;
struct tr *left, *right;
} btree, *btreeptr;
btree *createtree(int data) {
btree *newtree;
newtree = (btree *)malloc(sizeof(btree));
newtree->left = NULL;
newtree->right = NULL;
newtree->data = data;// Is the same as : (*p).data,
return newtree;
}
int main() {
btree *test[10];
btreeptr baum;
int i;
for (i = 0; i < 10; i++) {
test[i] = createtree(i);
}
baum = test[0];
test[0]->left = test[1];
test[0]->right = test[2];
test[1]->left = test[3];
test[1]->right = test[4];
test[2]->right = test[5];
test[4]->left = test[6];
test[5]->left = test[7];
test[5]->right = test[8];
test[7]->left = test[9];
printf("Size: %d\n", size(baum));
printf("Leaves: %d\n", numberOfLeaves(baum));
printf("Height: %d\n", height(baum));
return 0;
}
如果我对记忆的理解是错误的,我希望能得到纠正。
3条答案
按热度按时间ldioqlga1#
也许问你的老师为什么他们选择这样做会更好;我只能猜测。我的猜测是,他们希望您编写由最后的三个
printf
语句调用的函数,这些函数都不依赖于树节点中存储的值。我非常肯定,稍后,您将编写在树中插入和删除节点的函数,此时分配的临时向量将消失。但是,目前,必须有某种机制来为至少一棵测试树创建树边。如果你没有树来尝试,你将如何验证你的size
,height
和numberOfLeaves
的实现工作?你的导师可能正试图教你一些非常重要的东西:当你在写一个系统时,你应该尽可能快地(在你用未测试的函数写几百行代码之前)测试所有的东西,并且尽可能不依赖于其他未测试的函数。“模拟”测试树是一种不依赖于树插入函数(还没有写)的测试技术。
最后,数据字段将变得很重要。目前,将节点号存储为数据字段的值可能会在调试过程中有所帮助,因为它可以让您看到在任何时间点正在处理哪个节点。学习调试也是一项非常重要的技能。因此,您最终可能会决定感谢设计该课程材料的人。
332nm8kg2#
标题:使用树是不是浪费内存?
质疑自己的命运是件好事。
如果这个例子的目的是介绍一个被称为二叉树的数据结构(具有任意连接),那么这个例子就达到了它的目的。这样一个二叉树是一个经济的解决方案吗?
为了您的利益:
(And,我的古代编译器使用4字节指针,而不是8字节指针。)
示例中的"有效载荷"限于二进制值0到9,因此一个"四位字节"(4位)满足所示的要求。
有些人可能会认为上面的初始化需要太多的工作。下面是对应于OP版本的初始化。
也许有人会用一个简单的宏重写这些语句。
1bqhqjot3#
这是浪费内存吗?嗯,在某种意义上。代码把一堆东西排列成一个指针二叉树,但不对它们做任何事情。这些代码最终可能会被用于某些事情,这可能就是为什么它被展示给你。
另一件有趣的事情是,这段代码无意中形成了一个堆,它是二叉树的一个子集,可以用一个连续的数组来表示,其中索引为
i
的任何节点的子节点仅仅是条目i*2+1
和i*2+2
。这种风格的二叉树不需要指针,仅仅是因为所有的结构关系都由节点的位置暗示。尽管堆还有其他的需求和好处,但是如果初始数组中的值是随机的而不是连续的,那么这段代码就不能表示堆。同样的,大多数二叉树不能用连续数组表示,对于那些,这可能是最有效的表示,它也有一个好处,那就是很容易递归处理。