我创建了一个节点生成器,以获取n个元素如何相互连接。它是节点树中表示的父子层次结构。
我正在使用类似于以下代码的树生成器来找到最佳的两条链。
下面是代码:
public class NodeBuilder
{
private readonly List<IItem> _nestedItems;
private readonly IFactory<IItem> _factory;
private readonly NodeEqualityComparer _comparer;
private readonly List<Node> _nodes;
private WeightedComparer _weightedComparer;
private NodeComparer _nodeComparer;
private readonly NodeItemComparer _nodeItemComparer;
public NodeBuilder(List<IItem> nestedItems, IFactory<IItem> factory)
{
_nestedItems = nestedItems;
_factory = factory;
_comparer = new NodeEqualityComparer();
_nodeComparer = new NodeComparer();
_nodes = new List<Node>();
_weightedComparer=new WeightedComparer();
_nodeItemComparer = new NodeItemComparer(_factory.Comparer);
}
public IEnumerable<List<int>> GetTopChains(int collections)
{
if (_nodes.Count == 0) BuildNodes(collections);
var collection= GetIndexes().ToList();
collection.Sort(_weightedComparer);
return collection.Take(collections);
}
public class WeightedComparer : IComparer<List<int>>
{
public int Compare(List<int> x, List<int> y)
{
if (x == y) return 0;
if (x == null) return 1;
if (y == null) return -1;
return y.Count - x.Count;
}
}
private IEnumerable<List<int>> GetIndexes()
{
Dictionary<IItem,List<int>> indexers = new Dictionary<IItem, List<int>>();
_nodes.Sort(_nodeItemComparer);
foreach (var node in _nodes)
{
List< int> indexs=new List<int>();
int currSize = node.ChainSize;
var temp = node;
while (temp != null)
{
int index = _nestedItems.IndexOf(temp.Item);
if (index != -1) indexs.Add(index);
currSize--;
var temps = new List<Node>(temp.Childs.Where(x => x.ChainSize == currSize));
temps.Sort(_nodeComparer);
Dictionary<Node,List<int>> subIndexes = new Dictionary<Node, List<int>>();
if (!temps.Any()) temp = null;
foreach (var subTemp in temps)
{
var key = subTemp.Item;
if (indexers.ContainsKey(key))
{
var newList = new List<int>();
newList.AddRange(indexs);
newList.AddRange(indexers[key]);
subIndexes.Add(subTemp, newList);
}
if (subIndexes[subTemp].Count == node.ChainSize)
{
temp = subTemp;
indexers.Remove(subTemp.Item);
}
else
{
temp = null;
}
}
}
indexs = indexs.Distinct().ToList();
indexers.Add(node.Item,indexs);
}
return indexers.Values;
}
private void BuildNodes(int collections)
{
int total = _factory.TotalItems;
for (int i = collections * _factory.TotalItems - 1; i >= 0; i--)
{
var searchNode = new Node(_nestedItems[i], _factory.EqualityComparer);
Node node1 = _nodes.SingleOrDefault(x => _comparer.Equals(x, searchNode));
if (node1 == null)
{
node1 = searchNode;
node1.ChainSize = total;
_nodes.Add(node1);
}
}
for (int i = 0; i < collections * _factory.TotalItems; i++)
{
var searchNode = new Node(_nestedItems[i], _factory.EqualityComparer);
Node node1 = _nodes.SingleOrDefault(x => _comparer.Equals(x, searchNode));
for (int j = 0; j < collections * _factory.TotalItems; j++)
{
searchNode = new Node(_nestedItems[j], _factory.EqualityComparer);
Node node2 = _nodes.SingleOrDefault(x => _comparer.Equals(x, searchNode));
if (node2 == null)
{
node2 = searchNode;
_nodes.Add(node2);
}
if (_nestedItems[i].Constraint(_nestedItems[j]))
{
if (node1 != null)
{
int temp = node1.ChainSize - 1;
node2.ChainSize = temp;`enter code here`
if (!node1.Childs.Contains(node2, new NodeEqualityComparer()))
node1.Childs.Add(node2);
}
}
}
}
}
}
public class NodeItemComparer:IComparer<Node>
{
private readonly IComparer<IItem> _factoryComparer;
public NodeItemComparer(IComparer<IItem> factoryComparer)
{
_factoryComparer = factoryComparer;
}
public int Compare(Node x, Node y)
{
if (x == null & y == null) return 0;
if (x == y) return 0;
if (x == null) return 1;
if (y == null) return -1;
return _factoryComparer.Compare(y.Item, x.Item);
}
}
public class NodeComparer:IComparer<Node>
{
public int Compare(Node x, Node y)
{
if (x == null & y == null) return 0;
if (x == y) return 0;
if (x == null) return 1;
if (y == null) return -1;
return y.ChainSize - x.ChainSize;
}
}
public class NodeEqualityComparer : IEqualityComparer<Node>
{
public bool Equals(Node x, Node y)
{
if (x == null & y == null) return true;
if (x == y) return true;
if (x != y) return false;
return x.Equals(y);
}
public int GetHashCode(Node obj)
{
return obj.GetHashCode();
}
}
public class Node : IEquatable<Node>
{
public IItem Item { get; }
private readonly IEqualityComparer<IItem> _comparer;
public int ChainSize { get; set; }
public IList<Node> Childs { get; private set; }
public Node(IItem item, IEqualityComparer<IItem> comparer)
{
Item = item;
_comparer = comparer;
Childs = new List<Node>();
}
public override string ToString()
{
return Item.ItemName;
}
public bool Equals(Node other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return _comparer.Equals(Item, other.Item);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Node)obj);
}
public override int GetHashCode()
{
return (Item != null ? Item.GetHashCode() : 0);
}
public static bool operator ==(Node left, Node right)
{
return Equals(left, right);
}
public static bool operator !=(Node left, Node right)
{
return !Equals(left, right);
}
}
我正在寻找一种遍历树并找到两个层次连接项的方法。