我的N
点n
位置是平面。
(x(i), y(i))
是点号i
的位置。我想知道平面中有多少个簇,每个簇的大小是多少。群集是一组比r_0
距离更近的点。
例如,如果点数i
和数字j
之间的距离小于r_0
,点数j
和点数k
之间的距离也小于r_0
,所有三个点都在同一个群集中(点号i
和k
之间的距离不必小于r_0
)< / p>
如果我在C ++中知道x(i)
和y(i)
,有人能告诉我如何找到群集的数量和大小?
答案 0 :(得分:0)
能够将一组点划分为相似的组是data mining
的一部分。有一个算法wikipedia : DBScan可以进行您需要的计算,但需要访问每个节点。为了确定它是否是群集的一部分。
访问每个节点,并检查附近的节点以查看它们是否在距离增量内。如果找到足够的节点,则启动新的集群。然后,遍历集群中的节点以查看它们是否还具有属于集群的任何邻近邻居。当这些已经用尽时,使用新的(未经测试的节点)。
重复此操作,直到访问了所有节点,现在知道存在多少个集群的想法。
答案 1 :(得分:0)
如你所描述的那样,问题相当于找到图的连通分量,顶点是点和边r0-close关系。这将是时间上的二次方和空间线性(或者只是线性时间,如果你设法得到O(N)的边,并且每个点的平均边数是常数)。
时间上的线性和空间解的二次方可以通过在布尔矩阵中写入每个点来获得,以便在一次通过中构建图形。
通过使用空间树也可以找到Inbetween解决方案......
答案 2 :(得分:0)
小心完全未经测试的代码:
// some coordinates
struct point {
int x,y;
};
using PointVec = std::vector<point>;
// implicit data structure
struct psetdata {
point p;
int parent; // [Disjoint-set data structure][1]
psetdata(point& p) : p(p), parent(-1) {}
}
using PSet = std::vector<psetdata>;
void Collapse(PSet& pset, PSet::iterator p, int r_0) {
// reduce the hight of the implicit sets.
auto q = p;
auto parent = q->parent;
while (parent != pset[parent].parent) {
q->parent = pset[parent].parent;
q = &pset[parent];
parent = q->parent;
}
p->parent = q->parent; // ultimative parent
}
void Clusters(PointVec& points) {
PSet pset(points.begin(), points.end());
for (int idx = 0, auto& p = pset.begin(); p < pset.end(); p++, idx++) {
if (p.parent == -1)
p.parent = idx; // my own parent defines a set
for(auto ptry = p.next(); ptry < pset.end; ptry++) {
if (dist(p, ptry) < r_0) {
// ptry to a set.
Collapse(pset, p);
if (ptry->parent != -1) {
Collapse(pset, ptry);
pset[ptry->parent].parent = p->parent; // merge, need ultimative parent
}
ptry->parent = p->parent;
}
}
}
std::map<int, int> clusters;
// count clusters
for (auto p = pset.begin(); p != pset.end(); p++) {
Collapse(pset, p);
clusters[p->parent]++;
}
// print the sums
std::cout << "#clusters:" << sets.size() << "\n";
for (auto& c : clusters) {
std::cout << c.first << " size " << c.second << "\n";
}
}
int main() {
// some sample points
vector<point> points {{0,0}, {1,1}, {2,1}};
Clusters(points, 1);
}