我做了半个程序来完成一些主要的浮点运算。根据它开始使用的数据,它可以生成描述线段的非常大的数组。使用具有浮点数的笛卡尔坐标系记录这些线段的位置,以记录线的每一端的X,Y,Z位置。我不能使用X,Y,Z作为两端,所以我使用X,Y,Z作为开始,Q,R,S作为结束。所以基本上我要做的是,标记所有相同或翻转的行,使得Q,R,S第一行等于第二行的X,Y,Z和第一行的X,Y,Z等于Q,R,S在第二行。我目前的标记技术是将X设置为-1,因为我知道没有任何一行会以负坐标结束。我不想标记两行,只是除了一行之外的所有行。这是我目前的职能:
int filter(int lines)
{
printf("Filtering...\n");
refline=0;
scanline=1;
while(refline<(lines))
{
if( segpointX[refline] == segpointQ[scanline] && segpointY[refline] == segpointR[scanline] && segpointZ[refline] == segpointS[scanline] && segpointQ[refline] == segpointX[scanline] && segpointR[refline] == segpointY[scanline] && segpointS[refline] == segpointZ[scanline]
|| segpointX[refline] == segpointX[scanline] && segpointY[refline] == segpointY[scanline] && segpointZ[refline] == segpointZ[scanline] && segpointQ[refline] == segpointQ[scanline] && segpointR[refline] == segpointR[scanline] && segpointS[refline] == segpointS[scanline])
{
//printf("Origional: %f %f %f >< %f %f %f\n",segpointX[refline],segpointY[refline],segpointZ[refline],segpointQ[refline],segpointR[refline],segpointS[refline]);
//printf("Duplicate: %f %f %f >< %f %f %f\n\n",segpointX[scanline],segpointY[scanline],segpointZ[scanline],segpointQ[scanline],segpointR[scanline],segpointS[scanline]);
segpointX[scanline]=-1;
}
scanline++;
if(scanline==lines+1)
{
refline++;
scanline=refline+1;
}
}
return(0);
}
我知道我有多少行,这就是“行”整数。这段代码完全正常,但与我的其他程序相比,它的速度非常慢。我认为必须有一种方法可以更快地做到这一点,但我不确定如何。拥有这个功能真的很遗憾,因为它会拖延我的程序的其余部分,考虑到它的所有浮点数学运算速度非常快。如果没有比这更快的3倍速度,我可能只需要使用混乱的数据并使下一个功能足够聪明以忽略它。现在标记坏线非常有用,因为下一个功能很复杂,因为它没有尝试补偿我的数据中的重复。
答案 0 :(得分:2)
标记数组中重复项的经典方法是以某种方式对数组进行排序(O(N·logN)),然后在单次传递中标记/删除连续的相同元素(O(N));这具有总复杂度O(N·logN),而您的方法是O(N 2 )。
在您的情况下,所有困难归结为在您的数据点之间建立某种排序关系。
首先,我会规范化行的格式,以便以相同的方式表示等效行(相同的端点)。为此,每行比较元组(XYZ)/(QRS);如果Q小于X,则QRS与XYZ交换;如果X == Q,则检查Y和R,如果它们再与Z相等,则为S.
在此O(N)传递结束时,所有等效线具有相同的XYZQRS表示。
现在,如果您不想更改数据的表示形式(6个独立数组,其中struct
的单个数组将更简单,更高效),则对索引数组进行排序会更容易而不是实际数据(也可能更高效,甚至是唯一可行的可能性,如果您不想更改实际数据的顺序)。初始化一个整数数组,其数字从0到lines-1
;然后,您可以使用qsort
函数进行排序,并传递自定义比较器函数。
此功能将接收要比较的索引;你将使用这些索引来访问相应的XYZ / QRS并按顺序进行比较(将第一个元素的X与第二个元素的X进行比较,如果它们相等,则转到Ys,依此类推)。在排序结束时,您的索引数组将被排序,附近有相同的项目。
现在你可以做最后的传递了:扫描索引数组,并将当前索引对应的元素与下一个索引的元素进行比较:如果它们相等,则将第一个标记为重复;否则,您要么位于重复序列的最后一项,要么您处于新序列的开头,因此您需要(至少暂时)保留此项目。由于这些项目是有序的,因此相同的项目都在一行中,因此您可以一次性标记它们。
请注意,只有当您希望完全匹配时,这才能正常工作 - 即不会考虑FP不准确性。
答案 1 :(得分:0)
您的算法为N^2
。您应该可以在N log N
中执行此操作。但是,到达N log N
所需的复杂性将在一定程度上取决于您的数据。
假设您的数据在X方向上分布良好,我就是这样做的。
这不是100%正确但是得到粗糙的jist正确 - 你需要处理一些退化的情况..