[英]Remove duplicates from tree
我上课:
class Node
{
public string Name;
public string Address;
public int Id;
public List<Node> Children = new List<Node>;
public Node Parent;
}
表示树中的节点。
现在,我想从树中删除重复的节点。 以树为例:
注意:绿色Foo!=紫色Foo
哪种算法可以使我从树中删除重复项,从而得到以下结果:
-------------------------------------------
为了确定绿色Foo与紫色Foo不相等(!=),我想我需要具有另一个属性来存储节点的高度或其他一些属性,使我能够比较节点。 这是我认为我需要的属性(CompareId):
class Node
{
public string Name;
public string Address;
public int Id;
public List<Node> Children = new List<Node>();
public Node Parent;
public string CompareId // <----------------- Property I need to compare
{
get
{
var temp = this.Name + this.Address + this.Id;
if (this.Parent == null)
return temp;
else
return temp + this.Parent.CompareId;
}
}
}
如果您想创建同一棵树,我的代码是:
Node root = new Node() { Name = "Root", Id = 12, Address = "0x0A1F12" };
Node tom1 = new Node() { Name = "Tom", Id = 15, Address = "0x0F1A17", Parent=root };
root.Children.Add(tom1);
Node tom2 = new Node() { Name = "Tom", Id = 15, Address = "0x0F1A17", Parent = root };
root.Children.Add(tom2);
Node foo = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent=root };
root.Children.Add(foo);
Node foo1 = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent = tom1 };
tom1.Children.Add(foo1);
Node foo2 = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent = tom1 };
tom1.Children.Add(foo2);
Node foo3 = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent = tom2};
tom2.Children.Add(foo3);
Node foo4 = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent = tom2};
tom2.Children.Add(foo4);
Node joe1 = new Node() { Name = "Joe", Id = 99, Address = "0x605C2C", Parent = foo };
foo.Children.Add(joe1);
Node joe2 = new Node() { Name = "Joe", Id = 99, Address = "0x605C2C", Parent = foo };
foo.Children.Add(joe2);
请检查一下:
public class Node
{
public string Name;
public string Address;
public int Id;
public List<Node> Children;
public Node Parent;
public Node()
{
this.Children = new List<Node>();
}
public string CompareId
{
get
{
var temp = string.Concat(this.Name, this.Address, this.Id);
if (this.Parent == null)
return temp;
else
return string.Concat(temp, this.Parent.CompareId);
}
}
public override bool Equals(object OtherNode)
{
if (OtherNode is Node)
return this.CompareId.Equals(((Node)OtherNode).CompareId);
else
return false;
}
public static Node RemoveDuplicatesFromTree(Node RootNode)
{
if (RootNode.Children.Count > 0)
{
List<Node> OldChildrenList = new List<Node>();
OldChildrenList.AddRange(RootNode.Children);
foreach (Node CurrentChild in OldChildrenList)
{
if (RootNode.Children.Any<Node>(x => x.Equals(CurrentChild)))
{
List<Node> Duplicates = RootNode.Children.Where(x => x.Equals(CurrentChild)).ToList<Node>();
Duplicates.ForEach(x =>
{
CurrentChild.Children = CurrentChild.Children.Union<Node>(x.Children).ToList<Node>();
RootNode.Children.Remove(x);
});
RootNode.Children.Add(CurrentChild);
}
Node.RemoveDuplicatesFromTree(CurrentChild);
}
}
return RootNode;
}
}
仍然可以不用说。 用法:
Node.RemoveDuplicatesFromTree(root);
private void RemoveDuplicatesFromTree(Node root)
{
List<Node> nodesToBeremoved = new List<Node>();
root.Children.ForEach(p =>
{
if (!nodesToBeremoved.Contains(p))
{
nodesToBeremoved.AddRange(root.Children.Where(q => q.Name == p.Name && q != p));
}
});
for (int i = 0; i < nodesToBeremoved.Count; i++)
{
root.Children.Remove(nodesToBeremoved[i]);
}
if (root.Children != null && root.Children.Count > 0)
{
root.Children.ForEach(t => this.RemoveDuplicatesFromTree(t));
}
}
只需将根传递给此递归函数即可; 它将修剪同一级别中的所有重复项。 您无需创建比较ID。
static void RemoveDuplicates(ref Node root)
{
Dictionary<string, Node> nonDuplicates = new Dictionary<string, Node>();
Action<Node> traverseTree = null;
traverseTree = (x) =>
{
var compareId = x.CompareId;
if (nonDuplicates.ContainsKey(compareId)) // if there is a duplicate
{
x.Parent.Children.Remove(x); // remove node
}
else
{
nonDuplicates.Add(compareId, x);
}
// cannot use foreach loop because removing a node will result in exception
// keep traversing the tree
for (var i = x.Children.Count - 1; i >= 0; i--)
traverseTree(x.Children[i]);
};
traverseTree(root);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.