C语言中使用递归的堆栈溢出
我一直在疯狂地寻找答案,但毫无结果;我创建了一个四叉树,它应该对结构声明的1000多个对象的数组进行排序:C语言中使用递归的堆栈溢出,c,recursion,stack-overflow,C,Recursion,Stack Overflow,我一直在疯狂地寻找答案,但毫无结果;我创建了一个四叉树,它应该对结构声明的1000多个对象的数组进行排序: typedef struct node { char is_leaf; struct Particle *p; double m; double center_x; double center_y; double width; struct node *sw; struct node *nw; str
typedef struct node
{
char is_leaf;
struct Particle *p;
double m;
double center_x;
double center_y;
double width;
struct node *sw;
struct node *nw;
struct node *se;
struct node *ne;
} node;
使用以下函数将其转换为四叉树:
node* quadtree_insert(node *n, struct Particle *p, double center_x, double center_y, double width)
{
if(n == NULL)
{
n = (node*)malloc(sizeof(node));
n->is_leaf = 1;
n->p = p;
//n->m = 0.1;
n->sw = NULL;
n->se = NULL;
n->nw = NULL;
n->ne = NULL;
if(width < 1e-300){
n->width = 1e-300;
}
else
n->width = width;
return n;
}
else{
//n = (node*)malloc(sizeof(node));
double x;
double y;
if(width < 1e-300){
width = 1e-300;
}
if(n->is_leaf == 1) //! that is, if the node is not a branch
{
x = (double)n->p->x_pos;
y = (double)n->p->y_pos;
if(x <= center_x && y <= center_y) //! first quadrant
{
n->sw = quadtree_insert(n->sw, n->p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if(x <= center_x && y > center_y) //! second quadrant
{
n->nw = quadtree_insert(n->nw, n->p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if(x > center_x && y <= center_y) //! third quadrant
{
n->se = quadtree_insert(n->se, n->p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else //! fourth quadrant
{
n->ne = quadtree_insert(n->ne, n->p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
n->p = NULL; //! sets branch pointer to nothing...
n->is_leaf = 0;
}
//}
x = (double)p->x_pos;
y = (double)p->y_pos;
if(x <= center_x && y <= center_y) //! first quadrant
{
n->sw = quadtree_insert(n->sw, p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if(x <= center_x && y > center_y) //! second quadrant
{
n->nw = quadtree_insert(n->nw, p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if(x > center_x && y <= center_y) //! third quadrant
{
n->se = quadtree_insert(n->se, p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else //! fourth quadrant
{
n->ne = quadtree_insert(n->ne, p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
return n;
}
}
每次迭代后,在for循环之后,根是自由的,代码适用于小于~200的样本,valgrind没有给出这些样本的错误。除此之外还有一个中间函数,它对粒子执行一些算术运算:
double quadtree_calculate_forcey(struct Particle *p, node *n, double theta_max, double delta_t, int numP, double epsilon, double G)
{
if(n != NULL)
{
double d_x = (n->center_x - p->x_pos);
double d_y = (n->center_y - p->y_pos);
double r_2 = d_x * d_x + d_y * d_y;
r_2 = sqrt(r_2) + epsilon;
if(theta_max <= (n->width / r_2) && !n->is_leaf){
double a = 0;
if(n->sw != NULL)
a += quadtree_calculate_forcey(p, n->sw, theta_max, delta_t, numP, epsilon, G);
if(n->nw != NULL)
a += quadtree_calculate_forcey(p, n->nw, theta_max, delta_t, numP, epsilon, G);
if(n->se != NULL)
a += quadtree_calculate_forcey(p, n->se, theta_max, delta_t, numP, epsilon, G);
if(n->ne != NULL)
a += quadtree_calculate_forcey(p, n->ne, theta_max, delta_t, numP, epsilon, G);
return a;
}
else
{
double fy;
double mass;
if(d_x == 0 && d_y == 0){ // could be comparing the same star
//printf("RÖÖÖVHATT\n");
return 0;
}
else{
//printf("MASS : %f\n", n->m);
mass = n->m;
//printf("MASS : %f\n", mass);
fy = G * (mass * p->mass/ pow(r_2,3)) * d_y;
//printf("DY:%f DX:%f R_2:%f MASSA:%f\n",d_y, d_x, r_2 - epsilon, mass);
// printf("HIT SKA JAG: %f\n",d_y);
return fy;
}
}
}
return 0.0;
}
部分分析
我可以肯定问题主要是由于quadtree\u insert()
的主else
子句中的大量重复代码(接近重复代码)造成的。我已经用注释标记了片段1A和1B的开头,现在片段1B也用ifdef DO_REPEAT和endif构成框架
else
{
/* Fragment 1A */
// n = (node*)malloc(sizeof(node));
double x;
double y;
if (width < 1e-300)
{
width = 1e-300;
}
if (n->is_leaf == 1) // ! that is, if the node is not a branch
{
x = (double)n->p->x_pos;
y = (double)n->p->y_pos;
if (x <= center_x && y <= center_y) // ! first quadrant
{
n->sw = quadtree_insert(n->sw, n->p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if (x <= center_x && y > center_y) // ! second quadrant
{
n->nw = quadtree_insert(n->nw, n->p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if (x > center_x && y <= center_y) // ! third quadrant
{
n->se = quadtree_insert(n->se, n->p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else // ! fourth quadrant
{
n->ne = quadtree_insert(n->ne, n->p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
n->p = NULL; // ! sets branch pointer to nothing...
n->is_leaf = 0;
}
#ifdef DO_REPEAT
/* Fragment 1B */
x = (double)p->x_pos;
y = (double)p->y_pos;
if (x <= center_x && y <= center_y) // ! first quadrant
{
n->sw = quadtree_insert(n->sw, p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if (x <= center_x && y > center_y) // ! second quadrant
{
n->nw = quadtree_insert(n->nw, p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if (x > center_x && y <= center_y) // ! third quadrant
{
n->se = quadtree_insert(n->se, p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else // ! fourth quadrant
{
n->ne = quadtree_insert(n->ne, p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
#endif /* DO_REPEAT */
return n;
}
我使用了一个随机数生成器作为值表:
random -n 10 -T ' { %6:2[1:20]f, %6:2[-100:100]f, %6:2[-100:100]f, %6:2[-100:100]f, %6:2[-100:100]f },'
它在粒子6上为我崩溃了。在大纲中,他说:
即使在我运行它的Mac上,这也表明存在问题;被抑制的东西是可以的,但其余的大部分不是
当编译时没有-DDO_REPEAT
(正常编译),示例程序将运行到完成。当然,它会泄漏,因为没有代码来释放内存
Particle 0:
Particle 1:
Particle 2:
Particle 3:
Particle 4:
Particle 5:
Particle 6:
Particle 7:
Particle 8:
Particle 9:
==79683==
==79683== HEAP SUMMARY:
==79683== in use at exit: 26,580 bytes in 191 blocks
==79683== total heap usage: 273 allocs, 82 frees, 32,756 bytes allocated
==79683==
==79683== LEAK SUMMARY:
==79683== definitely lost: 4,200 bytes in 3 blocks
==79683== indirectly lost: 2,368 bytes in 7 blocks
==79683== possibly lost: 4,880 bytes in 45 blocks
==79683== still reachable: 6,440 bytes in 13 blocks
==79683== suppressed: 8,692 bytes in 123 blocks
==79683== Rerun with --leak-check=full to see details of leaked memory
请注意,使用的内存比以前少得多
如果由于缺少DO_REPEAT
而消除的代码实际上是至关重要的,那么错误要么在于该代码,要么在于片段1A中完成的设置工作。然而,在我看来,使用递归调用插入同一粒子两次可能是问题的根源
我还注意到代码中没有使用quadtree\u calculate\u forcey()
函数;它绝对不是MCVE的一部分
需要片段1B 建议: 请注意,“重复”代码的形式相同,但不详细。也就是说,片段1B使用
n->p
,而片段1A使用p
。我认为这是有目的的:这个想法似乎是将所有数据(粒子)强制输出到叶节点
并申明:
正如John所说,每个粒子都应该占据一个端点节点。我的怀疑是,这与运动有关,行星排列得如此之好,以至于必须进行荒谬的迭代才能打开两个自由正方形。但我看不到解决我问题的办法,有什么想法吗
逻辑上存在问题,尽管我不完全确定问题是什么。我要做的第一步是在quadtree\u insert()
中的代码中添加一些指令插入,如下所示:
static node *quadtree_insert(node *n, struct Particle *p, double center_x, double center_y, double width)
{
printf("Centre (X,Y) = (%6.2f,%6.2f)\n", center_x, center_y);
if (n == NULL)
{
n = (node *)malloc(sizeof(node));
n->is_leaf = 1;
n->p = p;
// n->m = 0.1;
n->sw = NULL;
n->se = NULL;
n->nw = NULL;
n->ne = NULL;
if (width < 1e-300)
{
n->width = 1e-300;
}
else
n->width = width;
return n;
}
else
{
// n = (node*)malloc(sizeof(node));
double x;
double y;
if (width < 1e-300)
{
width = 1e-300;
}
if (n->is_leaf == 1) // ! that is, if the node is not a branch
{
x = (double)n->p->x_pos;
y = (double)n->p->y_pos;
if (x <= center_x && y <= center_y) // ! first quadrant
{
printf("Recurse SW 1: ");
n->sw = quadtree_insert(n->sw, n->p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if (x <= center_x && y > center_y) // ! second quadrant
{
printf("Recurse NW 1: ");
n->nw = quadtree_insert(n->nw, n->p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if (x > center_x && y <= center_y) // ! third quadrant
{
printf("Recurse SE 1: ");
n->se = quadtree_insert(n->se, n->p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else // ! fourth quadrant
{
printf("Recurse NE 1: ");
n->ne = quadtree_insert(n->ne, n->p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
n->p = NULL; // ! sets branch pointer to nothing...
n->is_leaf = 0;
}
x = (double)p->x_pos;
y = (double)p->y_pos;
if (x <= center_x && y <= center_y) // ! first quadrant
{
printf("Recurse SW 2: ");
n->sw = quadtree_insert(n->sw, p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if (x <= center_x && y > center_y) // ! second quadrant
{
printf("Recurse NW 2: ");
n->nw = quadtree_insert(n->nw, p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if (x > center_x && y <= center_y) // ! third quadrant
{
printf("Recurse SE 2: ");
n->se = quadtree_insert(n->se, p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else // ! fourth quadrant
{
printf("Recurse NE 2: ");
n->ne = quadtree_insert(n->ne, p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
return n;
}
}
我对这里的一些处理和粒子4的条目数量感到有点惊讶。这可能说明了问题所在
然后它处理粒子6:
Particle 6: Centre (X,Y) = ( 0.50, 0.50)
Recurse SW 2: Centre (X,Y) = ( 0.25, 0.25)
Recurse SW 1: Centre (X,Y) = ( 0.12, 0.12)
Recurse SW 2: Centre (X,Y) = ( 0.12, 0.12)
Recurse SW 1: Centre (X,Y) = ( 0.06, 0.06)
Recurse SW 2: Centre (X,Y) = ( 0.06, 0.06)
Recurse SW 1: Centre (X,Y) = ( 0.03, 0.03)
Recurse SW 2: Centre (X,Y) = ( 0.03, 0.03)
Recurse SW 1: Centre (X,Y) = ( 0.02, 0.02)
Recurse SW 2: Centre (X,Y) = ( 0.02, 0.02)
Recurse SW 1: Centre (X,Y) = ( 0.01, 0.01)
Recurse SW 2: Centre (X,Y) = ( 0.01, 0.01)
Recurse SW 1: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 2: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 1: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 2: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 1: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 2: Centre (X,Y) = ( 0.00, 0.00)
从那以后就变得很乏味了。你需要问的问题是“这一点会发生什么”?有一个函数来转储四叉树结构可能也是个好主意
这基本上表明您尚未充分分析添加点的条件。我不清楚当插入位于东南或东北象限时,为什么要将中心坐标乘以1.5,当插入位于西南或西北象限时,为什么要将中心坐标乘以0.5(也不清楚为什么要使用加法乘法而不是简单的乘法)
宽度小于1e-300
的测试有点令人担忧。假设您使用值1.0
调用函数,那么每次递归时将宽度减半需要一段时间才能变小
更好的追踪可以报告x
和y
的值以及中心坐标。部分分析
我可以肯定问题主要是由于quadtree\u insert()
的主else
子句中的大量重复代码(接近重复代码)造成的。我已经用注释标记了片段1A和1B的开头,现在片段1B也用ifdef DO_REPEAT和endif构成框架
else
{
/* Fragment 1A */
// n = (node*)malloc(sizeof(node));
double x;
double y;
if (width < 1e-300)
{
width = 1e-300;
}
if (n->is_leaf == 1) // ! that is, if the node is not a branch
{
x = (double)n->p->x_pos;
y = (double)n->p->y_pos;
if (x <= center_x && y <= center_y) // ! first quadrant
{
n->sw = quadtree_insert(n->sw, n->p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if (x <= center_x && y > center_y) // ! second quadrant
{
n->nw = quadtree_insert(n->nw, n->p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if (x > center_x && y <= center_y) // ! third quadrant
{
n->se = quadtree_insert(n->se, n->p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else // ! fourth quadrant
{
n->ne = quadtree_insert(n->ne, n->p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
n->p = NULL; // ! sets branch pointer to nothing...
n->is_leaf = 0;
}
#ifdef DO_REPEAT
/* Fragment 1B */
x = (double)p->x_pos;
y = (double)p->y_pos;
if (x <= center_x && y <= center_y) // ! first quadrant
{
n->sw = quadtree_insert(n->sw, p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if (x <= center_x && y > center_y) // ! second quadrant
{
n->nw = quadtree_insert(n->nw, p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if (x > center_x && y <= center_y) // ! third quadrant
{
n->se = quadtree_insert(n->se, p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else // ! fourth quadrant
{
n->ne = quadtree_insert(n->ne, p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
#endif /* DO_REPEAT */
return n;
}
我使用了一个随机数生成器作为值表:
random -n 10 -T ' { %6:2[1:20]f, %6:2[-100:100]f, %6:2[-100:100]f, %6:2[-100:100]f, %6:2[-100:100]f },'
它在粒子6上为我崩溃了。在大纲中,他说:
即使在我运行它的Mac上,这也表明存在问题;被抑制的东西是可以的,但其余的大部分不是
当编译时没有-DDO_REPEAT
(正常编译),示例程序将运行到完成。当然,它会泄漏,因为没有代码来释放内存
Particle 0:
Particle 1:
Particle 2:
Particle 3:
Particle 4:
Particle 5:
Particle 6:
Particle 7:
Particle 8:
Particle 9:
==79683==
==79683== HEAP SUMMARY:
==79683== in use at exit: 26,580 bytes in 191 blocks
==79683== total heap usage: 273 allocs, 82 frees, 32,756 bytes allocated
==79683==
==79683== LEAK SUMMARY:
==79683== definitely lost: 4,200 bytes in 3 blocks
==79683== indirectly lost: 2,368 bytes in 7 blocks
==79683== possibly lost: 4,880 bytes in 45 blocks
==79683== still reachable: 6,440 bytes in 13 blocks
==79683== suppressed: 8,692 bytes in 123 blocks
==79683== Rerun with --leak-check=full to see details of leaked memory
请注意,使用的内存比以前少得多
如果由于缺少DO_REPEAT
而消除的代码实际上是至关重要的,那么错误要么在于该代码,要么在于片段1A中完成的设置工作。然而,在我看来,使用递归调用插入同一粒子两次可能是问题的根源
我还注意到代码中没有使用quadtree\u calculate\u forcey()
函数;它绝对不是MCVE的一部分
需要片段1B
建议:
请注意,“重复”代码的形式相同,但不详细。也就是说,片段1B使用n->p
,而片段1A使用p
。我认为这是有目的的:这个想法似乎是将所有数据(粒子)强制输出到叶节点
并申明:
正如John所说,每个粒子都应该占据一个端点节点。我的怀疑是,这与运动有关,行星排列得如此之好,以至于必须进行荒谬的迭代才能打开两个自由正方形。但我看不到解决我问题的办法,有什么想法吗
逻辑上存在问题,尽管我不完全确定问题是什么。我要做的第一步是在quadtree\u insert()
中的代码中添加一些指令插入,如下所示:
static node *quadtree_insert(node *n, struct Particle *p, double center_x, double center_y, double width)
{
printf("Centre (X,Y) = (%6.2f,%6.2f)\n", center_x, center_y);
if (n == NULL)
{
n = (node *)malloc(sizeof(node));
n->is_leaf = 1;
n->p = p;
// n->m = 0.1;
n->sw = NULL;
n->se = NULL;
n->nw = NULL;
n->ne = NULL;
if (width < 1e-300)
{
n->width = 1e-300;
}
else
n->width = width;
return n;
}
else
{
// n = (node*)malloc(sizeof(node));
double x;
double y;
if (width < 1e-300)
{
width = 1e-300;
}
if (n->is_leaf == 1) // ! that is, if the node is not a branch
{
x = (double)n->p->x_pos;
y = (double)n->p->y_pos;
if (x <= center_x && y <= center_y) // ! first quadrant
{
printf("Recurse SW 1: ");
n->sw = quadtree_insert(n->sw, n->p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if (x <= center_x && y > center_y) // ! second quadrant
{
printf("Recurse NW 1: ");
n->nw = quadtree_insert(n->nw, n->p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if (x > center_x && y <= center_y) // ! third quadrant
{
printf("Recurse SE 1: ");
n->se = quadtree_insert(n->se, n->p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else // ! fourth quadrant
{
printf("Recurse NE 1: ");
n->ne = quadtree_insert(n->ne, n->p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
n->p = NULL; // ! sets branch pointer to nothing...
n->is_leaf = 0;
}
x = (double)p->x_pos;
y = (double)p->y_pos;
if (x <= center_x && y <= center_y) // ! first quadrant
{
printf("Recurse SW 2: ");
n->sw = quadtree_insert(n->sw, p, center_x * 0.5, center_y * 0.5, width * 0.5);
}
else if (x <= center_x && y > center_y) // ! second quadrant
{
printf("Recurse NW 2: ");
n->nw = quadtree_insert(n->nw, p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
else if (x > center_x && y <= center_y) // ! third quadrant
{
printf("Recurse SE 2: ");
n->se = quadtree_insert(n->se, p, center_x + center_x * 0.5, center_y * 0.5, width * 0.5);
}
else // ! fourth quadrant
{
printf("Recurse NE 2: ");
n->ne = quadtree_insert(n->ne, p, center_x + center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
return n;
}
}
我对一些程序感到有点惊讶
Particle 0: Centre (X,Y) = ( 0.50, 0.50)
Particle 1: Centre (X,Y) = ( 0.50, 0.50)
Recurse NE 1: Centre (X,Y) = ( 0.75, 0.75)
Recurse SE 2: Centre (X,Y) = ( 0.75, 0.25)
Particle 2: Centre (X,Y) = ( 0.50, 0.50)
Recurse SE 2: Centre (X,Y) = ( 0.75, 0.25)
Recurse SE 1: Centre (X,Y) = ( 1.12, 0.12)
Recurse SE 2: Centre (X,Y) = ( 1.12, 0.12)
Recurse SE 1: Centre (X,Y) = ( 1.69, 0.06)
Recurse SE 2: Centre (X,Y) = ( 1.69, 0.06)
Recurse SW 1: Centre (X,Y) = ( 0.84, 0.03)
Recurse SE 2: Centre (X,Y) = ( 2.53, 0.03)
Particle 3: Centre (X,Y) = ( 0.50, 0.50)
Recurse SW 2: Centre (X,Y) = ( 0.25, 0.25)
Particle 4: Centre (X,Y) = ( 0.50, 0.50)
Recurse NE 2: Centre (X,Y) = ( 0.75, 0.75)
Recurse NE 1: Centre (X,Y) = ( 1.12, 1.12)
Recurse NE 2: Centre (X,Y) = ( 1.12, 1.12)
Recurse NE 1: Centre (X,Y) = ( 1.69, 1.69)
Recurse NE 2: Centre (X,Y) = ( 1.69, 1.69)
Recurse NE 1: Centre (X,Y) = ( 2.53, 2.53)
Recurse NE 2: Centre (X,Y) = ( 2.53, 2.53)
Recurse NE 1: Centre (X,Y) = ( 3.80, 3.80)
Recurse NE 2: Centre (X,Y) = ( 3.80, 3.80)
Recurse NE 1: Centre (X,Y) = ( 5.70, 5.70)
Recurse NE 2: Centre (X,Y) = ( 5.70, 5.70)
Recurse NE 1: Centre (X,Y) = ( 8.54, 8.54)
Recurse NE 2: Centre (X,Y) = ( 8.54, 8.54)
Recurse NE 1: Centre (X,Y) = ( 12.81, 12.81)
Recurse NE 2: Centre (X,Y) = ( 12.81, 12.81)
Recurse NE 1: Centre (X,Y) = ( 19.22, 19.22)
Recurse NE 2: Centre (X,Y) = ( 19.22, 19.22)
Recurse NE 1: Centre (X,Y) = ( 28.83, 28.83)
Recurse NE 2: Centre (X,Y) = ( 28.83, 28.83)
Recurse NE 1: Centre (X,Y) = ( 43.25, 43.25)
Recurse NE 2: Centre (X,Y) = ( 43.25, 43.25)
Recurse NE 1: Centre (X,Y) = ( 64.87, 64.87)
Recurse NE 2: Centre (X,Y) = ( 64.87, 64.87)
Recurse SE 1: Centre (X,Y) = ( 97.31, 32.44)
Recurse NE 2: Centre (X,Y) = ( 97.31, 97.31)
Particle 5: Centre (X,Y) = ( 0.50, 0.50)
Recurse NW 2: Centre (X,Y) = ( 0.25, 0.75)
Particle 6: Centre (X,Y) = ( 0.50, 0.50)
Recurse SW 2: Centre (X,Y) = ( 0.25, 0.25)
Recurse SW 1: Centre (X,Y) = ( 0.12, 0.12)
Recurse SW 2: Centre (X,Y) = ( 0.12, 0.12)
Recurse SW 1: Centre (X,Y) = ( 0.06, 0.06)
Recurse SW 2: Centre (X,Y) = ( 0.06, 0.06)
Recurse SW 1: Centre (X,Y) = ( 0.03, 0.03)
Recurse SW 2: Centre (X,Y) = ( 0.03, 0.03)
Recurse SW 1: Centre (X,Y) = ( 0.02, 0.02)
Recurse SW 2: Centre (X,Y) = ( 0.02, 0.02)
Recurse SW 1: Centre (X,Y) = ( 0.01, 0.01)
Recurse SW 2: Centre (X,Y) = ( 0.01, 0.01)
Recurse SW 1: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 2: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 1: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 2: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 1: Centre (X,Y) = ( 0.00, 0.00)
Recurse SW 2: Centre (X,Y) = ( 0.00, 0.00)
else if (x <= center_x && y > center_y) // ! second quadrant
{
n->nw = quadtree_insert(n->nw, n->p, center_x * 0.5, center_y + center_y * 0.5, width * 0.5);
}
// adjust as needed:
#define MIN_PARTICLE_SEPARATION 1e-300
void quadtree_insert_helper(node *n, Particle *p, double center_x,
double center_y, double width) {
width *= 0.5;
double new_center_x = center_x
+ width * ((p->x_pos <= center_x) ? -0.5 : 0.5);
double new_center_y = center_y
+ width * ((p->y_pos <= center_y) ? -0.5 : 0.5);
node **quad;
if (new_center_x <= center_x && new_center_y <= center_y) {
//! first quadrant
quad = &n->sw;
} else if (new_center_x <= center_x && new_center_y > center_y) {
//! second quadrant
quad = &n->nw;
} else if (new_center_x > center_x && new_center_y <= center_y) {
//! third quadrant
quad = &n->se;
} else {
//! fourth quadrant
quad = &n->ne;
}
*quad = quadtree_insert(*quad, p, new_center_x, new_center_y, width);
}
node* quadtree_insert(node *n, struct Particle *p, double center_x,
double center_y, double width) {
if (n == NULL) {
n = malloc(sizeof(*n));
n->is_leaf = 1;
n->p = p;
//n->m = 0.1;
n->sw = NULL;
n->se = NULL;
n->nw = NULL;
n->ne = NULL;
n->center_x = center_x;
n->center_y = center_y;
n->width = width;
} else if (n->is_leaf && (with <= MIN_PARTICLE_SEPARATION)) {
// ... merge particles ...
} else {
if (n->is_leaf) { //! that is, if the node is not a branch
quadtree_insert_helper(n, n->p, center_x, center_y, width);
//! the node is now a branch
n->p = NULL;
n->is_leaf = 0;
}
quadtree_insert_helper(n, p, center_x, center_y, width);
}
return n;
}