我已经实现了一种用于层次聚类的算法和一种在C#中绘制树形图的简单方法。 现在我想添加树状图截止方法和另一个用于着色树状图分支的方法。 什么是一个有效的算法呢?
cutoff方法应该返回一个树形图节点列表,其下每个子树代表一个簇。 我的数据结构是一个由根节点
表示的简单二叉树节点结构如下:
class DendrogramNode
{
String Id { get; set; }
DendrogramNode LeftNode { get; set; }
DendrogramNode RightNode { get; set; }
Double Height { get; set; }
}
CutOff方法应具有以下签名
List<DendrogramNode> CufOff(int numberOfClusters)
到目前为止我做了什么:
我的第一次尝试是创建所有 DendrogramNodes 的列表,并按降序对它们进行排序。然后从排序列表中获取 numberOfClusters 的第一个条目。 - 这失败了,因为我们最终可能会得到一个包含所有子节点也属于的父节点的列表。在这种情况下,应删除父节点。
第二次尝试是创建所有链接的列表并以链接顺序存储它们。这样我就可以使用最后的 numberOfClusters 并使用它们来创建截止列表 - 这很好用,但我不喜欢存储这些信息,因为它很难维护(特别是对于迭代聚类)
它看起来像一个简单的问题,但不知怎的,我已经堆积在此。你能帮我找到一个有效的解决方案吗?
我认为解决方案1在某些方面是可行的,但是当应用程序的所有子节点也在列表中时,应该有一些部分删除父节点,ad应该以某种方式迭代/递归,因为删除节点会创建空间添加另一个。
答案 0 :(得分:0)
好的解决方案是使用PriorityQueue(优先级是节点高度的节点):
private List<DendrogramNode> GetCutOffNodes(int numberOfClusters)
{
numberOfClusters = System.Math.Min(this.NumberOfInstances, System.Math.Max(numberOfClusters, 0));
PriorityQueue<DendrogramNode, DendrogramNodeDescendingComparer> queue = newPriorityQueue<DendrogramNode, DendrogramNodeDescendingComparer>();
queue.Enqueue(this.Root);
intclusters2Find = numberOfClusters - 1;
DendrogramNodenode = null;
while(queue.Count > 0 && clusters2Find > 0)
{
node = queue.Dequeue();
if(node.LeftNode != null)
queue.Enqueue(node.LeftNode);
if(node.RightNode != null)
queue.Enqueue(node.RightNode);
clusters2Find--;
}
List<DendrogramNode> result = new List<DendrogramNode>(numberOfClusters);
while(queue.Count > 0)
result.Add(queue.Dequeue());
return result;
}