集团

2013-11-15 68 views
1

我希望能够找到一种有效的方式来组中的树形图,其具有以下特征的项目的项目共享在C#中相同的家长和孩子:集团

关于树图,它有这样的多层如果绘制水平:

(0,0)--(1,0)--(2,0) 
    \ \-(1,1)--(2,1) 
    \--(1,2)--/ 
  1. 对于由类节点建模的节点(X,Y)中,x是它的 “水平”,而y是它的 “索引”。对于任何边,我们只允许这个边的两个节点的顺序索引,所以(1,2) - (3,2)是禁止的。
  2. 允许多个根:(0,0)(0,1)...等。

关于“基团中的项目”:由于树的数据源中 有像节点:

(3,5)--(4,10)--(5,5) 
    \ \-(4,11)-//
    \ .... /
    \--(4,80)--/ 

我想组像那些节点(4,10〜80)以上到一个节点,这些节点共享相同特性

  1. 具有它们共享
  2. 仅具有1的子节点,其它们共享
  3. 仅1父节点
  4. 还需要解决他们只有共同父母(或共同孩子)但根本没有子女(或父母)的情况。

使用一个特殊的类CompoundNode,Node的一个子类。

这里是一个骨架类节点:

public class Node 
{ 
    public Node(string id) 
    { 
     Id = id; 
    } 

    public string Id { get; set; } 

    private readonly List<Node> children = new List<Node>(); 
    public List<Node> Children { get { return children; } } 
    private readonly List<Node> parents = new List<Node>(); 
    public List<Node> Parents { get { return parents; } } 

    protected bool Equals(Node other) 
    { 
     .... 
    } 

    public override bool Equals(object obj) 
    { 
     .... 
    } 

    public override int GetHashCode() 
    { 
     return (Id != null ? Id.GetHashCode() : 0); 
    } 

    public override string ToString() 
    { 
     .... 
    } 
} 

谢谢!

编辑:

下面是解我做(提取的关系,而无需修改树),如果不解决零父母或零孩子的情况:

 var relationships = new List<Tuple<string, string, string>>(); 

     foreach (var middle in nodes) 
     { 
      if (middle.Children.Count == 1 && middle.Parents.Count == 1) 
      { 
       var child = middle.Children[0]; 
       var parent = middle.Parents[0]; 
       relationships.Add(new Tuple<string, string, string>(parent.Id, middle.Id, child.Id)); 
      } 
     } 
     var groups = relationships.GroupBy(t => new { t.Item1, t.Item3 }).Where(a => a.Count() > 1); 

     var toGroupedRelations = groups.Cast<IEnumerable<Tuple<string, string, string>>>().ToList(); 
+0

这是认真的功课。 –

+0

你的树有多大?这会对算法的选择产生重大影响。 – Baldrick

+0

@ P.Brian.Mackey,nah im正在基金公司工作;) – ender

回答

0

确定 - 这里是第一次尝试。无论如何应该给你一些好的指点:

var nodes = new List<Node>(); 

// !! populate your nodes list with all your real nodes first! 

// filter to nodes with at most 1 parent and 1 child 
// group by a tuple containing the parent (if it exists) and the child (if it exists) 
var grouped = nodes.Where(i => i.Children.Count <= 1 && i.Parents.Count <= 1) 
    .GroupBy(i => 
     new Tuple<Node, Node>(i.Parents.Count == 0 ? null : i.Parents[0], 
           i.Children.Count == 0 ? null : i.Children[0])); 

// go through your groups - each one should be a cluster of nodes to be merged 
foreach (var group in grouped) 
{ 
    // get the first node in the group (which one is arbitrary if we're merging anyway) 
    var node = group.First(); 

    // if this group has a parent 
    if (node.Parents.Count == 1) 
    { 
     // change the parent to only have one child - this one! 
     node.Parents[0].Children.Clear(); 
     node.Parents[0].Children.Add(node); 
    } 

    // if this group has a child 
    if (node.Children.Count == 1) 
    { 
     // change the child to only have one parent - this one! 
     node.Children[0].Parents.Clear(); 
     node.Children[0].Parents.Add(node); 
    } 
} 
+0

tks。 GroupBy是我正在寻找的! – ender