【问题标题】:Remove duplicates from tree从树中删除重复项
【发布时间】:2012-08-28 14:38:20
【问题描述】:

我有课:

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);

【问题讨论】:

  • 具有不同子节点的重复节点怎么办?
  • 是否总是保证重复的父节点也有完全重复的子树?编辑:哇@saj 我们同时想到了同样的事情:)
  • 如果你有一个红汤姆有两个孩子,一个红汤姆有三个孩子,你的算法的输出是什么?
  • 我不知道如何处理具有不同子节点的重复节点。我想即使它们不同,也要删除它们。
  • @TonoNam:如果在你自己的数据和你自己的规范中不知道如何处理它们,我们应该怎么做想办法?你想要结果是什么?

标签: c# data-structures tree duplicates


【解决方案1】:

请检查一下:

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);

【讨论】:

    【解决方案2】:
    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。

    【讨论】:

      【解决方案3】:
      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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-04
        • 2015-09-30
        • 2018-08-21
        • 1970-01-01
        • 2013-12-17
        • 2015-10-11
        • 2010-09-19
        • 2011-08-24
        相关资源
        最近更新 更多