我现在正在实现模拟N体问题的Barnes-Hut算法。我只想问关于建筑树的部分。
我做了两个函数来为它构建树。
我递归地构建树,并在构建时打印每个节点的数据,一切看起来都是正确的,但当程序返回到主函数时,只有树的根和根的子节点存储值。其他节点的值没有被存储,这很奇怪,因为我在递归过程中打印了它们,它们应该被存储。
这是经过修改的代码的一部分,我认为问题可能在哪里:
#include<...>
typedef struct node{
int data;
struct node *child1,*child2;
}Node;
Node root; // a global variable
int main(){
.
set_root_and_build(); // is called not only once cuz it's actually in a loop
traverse(&root);
.
}
下面是函数set_root_and_build():
我已经将子指针设置为NULL,但是一开始并没有显示出来。
void set_root_and_build(){
root.data = ...;
..// set child1 and child2 =NULL;
build(&root,...); // ... part are values of data for it's child
}
并构建:
void build(Node *n,...){
Node *new1, *new2 ;
new1 = (Node*)malloc(sizeof(Node));
new2 = (Node*)malloc(sizeof(Node));
... // (set data of new1 and new2 **,also their children are set NULL**)
if(some condition holds for child1){ // else no link, so n->child1 should be NULL
build(new1,...);
n->child1 = new1;
//for debugging, print data of n->child1 & and->child2
}
if(some condition holds for child2){ // else no link, so n->child2 should be NULL
build(new2,...);
n->child1 = new2;
//for debugging, print data of n->child1 & and->child2
}
}
树中的节点可能有1~2个孩子,这里不是所有的节点都有2个孩子。
程序在构建()
函数递归中打印出正确的数据,但当它返回到main函数并调用遍历()
时,由于分段错误而失败。
我尝试在traverse()
中打印所有内容,发现只有根和根。child1,根。child2存储的值与我提到的一样。
由于我必须多次调用Build()
,即使并行调用,new1和new2也不能定义为全局变量。(但我不认为它们会导致这里的问题)。
有人知道哪里出错了吗?
带有调试信息的遍历部分:
void traverse(Node n){
...//print out data of n
if(n.child1!=NULL)
traverse(*(n.child1))
...//same for child2
}
遍历树的问题是,在找到一个NULL节点指针之前,您必须处理树。
不幸的是,当您创建节点时,这些节点既不是用malloc()
初始化的,也不是用new
初始化的(它将用calloc(()<-code>初始化,但cpp代码中的这种做法与
maloc()
一样糟糕)。因此,您的遍历将继续在随机指针的梦幻世界中循环/递归。
我建议你利用cpp的优势,稍微改变你的结构:
struct Node { // that's C++: no need for typedef
int data;
struct node *child1,*child2;
Node() : data(0), child1(nullptr), child2(nullptr) {} // Makes sure that every created are first initalized
};
然后再把你的老马洛克扔掉。并构造代码以避免不必要的分配:
if(some condition holds for child1){ // else no link, so n->child1 should be NULL
new1=new Node; // if you init it here, no need to free in an else !!
build(new1,...);
n->child1 = new1;
...
}
if (... child2) { ... }
但是,请注意,使用< code>new
分配的点应使用< code>delete释放,并使用< code>free()注释。
编辑:您的代码片段不匹配:
traverse(&root); // you send here a Node*
void traverse(Node n){ // but your function defines an argument by value !
...
}
检查你没有忽略来自编译器的一些警告,并且你的代码中没有滥用强制转换。
当条件不成立时,您可能没有正确设置n
的子级。您可能需要这样做:
void set_root_and_build()
{
root.data = ...;
build(&root,...); // ... part are values of data for it's child
}
void build(Node *n,...)
{
n->child1 = n->child2 = NULL;
Node *new1, *new2;
new1 = (Node*) malloc(sizeof(Node));
new2 = (Node*) malloc(sizeof(Node));
// set data of new1 and new2 somehow (read from stdin?)
if (some condition holds for new1)
{
n->child1 = new1;
build(n->child1,...);
//for debugging, print data of n->child1
}
else
free(new1); // or whatever else you need to do to reclaim new1
if (some condition holds for new2)
{
n->child2 = new2;
build(n->child2,...);
//for debugging, print data of n->child2
}
else
free(new2); // or whatever else you need to do to reclaim new2
}
当然,您还应该检查malloc()的返回值并处理错误。
此外,您的遍历有点奇怪,因为它通过复制而不是引用递归。你有理由这么做吗?如果不是,那么也许你想要:
void traverse(Node *n)
{
...//print out data of n
if (n->child1 != NULL)
traverse(n->child1)
...//same for child2
}
主要内容:获取结构体成员,结构体指针作为函数参数当一个 指针变量指向结构体时,我们就称它为 结构体指针。 C语言结构体指针的定义形式一般为: struct 结构体名 *变量名; 下面是一个定义结构体指针的实例: 也可以在定义结构体的同时定义结构体指针: 注意,结构体变量名和数组名不同,数组名在表达式中会被转换为数组指针,而结构体变量名不会,无论在任何表达式中它表示的都是整个集合本身,要想取得结构体变量的地址,必须在前面加 ,所以给 pstu 赋
本文向大家介绍使用递归[JavaScript]创建层次结构,包括了使用递归[JavaScript]创建层次结构的使用技巧和注意事项,需要的朋友参考一下 示例 输出
我正在学习链表,以及如何在C中使用结构和指针创建链表。下面我举一个例子。据我所知,被调用的将头节点所在的结构的开始内存位置作为参数传递。push()函数的参数将结构节点作为指向指针的指针,因此它作为引用传递,而不是实际副本。因此,我们的的第一个指针只是指向头部节点的内存位置的指针,第二个指针指向该值,该值是头部节点指向的下一个内存位置。我们通过为结构节点分配一些内存,在结构节点内创建一个名为new
问题内容: 我有一个将位置链接在一起的数据库表;一个位置可以在一个位置,也可以在另一个位置内。 这是深入探讨MySQL / PHP的深度: 在给定父级位置的情况下,如何使用MySQL如何获得其所有后代位置,无论深度如何? 问题答案: mysql.com上有 一篇漂亮的文章 ,概述了管理分层数据的各种方法。我认为它为您的问题提供了完整的解决方案,并显示了各种不太简单但较快的方法(例如嵌套集)。
问题内容: 我正在尝试为C库编写SWIG包装器,该包装器使用指向其结构中函数的指针。我不知道如何处理包含函数指针的结构。下面是一个简化的示例。 test.i: 样本会议: 有人知道是否有可能让 t.my_func(1) 返回2吗? 谢谢! 问题答案: 我找到了答案。如果我将函数指针声明为SWIG“成员函数”,则它似乎可以按预期工作: 会议: 我希望不需要编写任何特定于SWIG的自定义代码(我希望仅
问题内容: 我不理解以下代码的行为。在创建作为结构指针切片的匹配结构列表时,代码始终会打印原始数组的最后一个元素(实际上不是匹配项),它会打印12和12。但是,如果将匹配项更改为[]窗口小部件代替[] * Widget,然后将输出10和11。 为什么是这样? 问题答案: 那是因为当您使用指针时,您将添加到数组。 请注意,实际上这是循环中使用的局部变量,因此,这不是您要添加到数组中的地址。 (即使变