Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove duplicates from tree

I have the class:

class Node
{
    public string Name;
    public string Address;
    public int Id;
    public List<Node> Children = new List<Node>;
    public Node Parent;
}

To represent a node in a tree.

Now I will like to remove the duplicate nodes from a tree. Take for instance the tree:

enter image description here

Note: green Foo != purple Foo

What algorithm will enable me to remove the duplicates from the tree in order to end up with:

------------------------------------------- enter image description here

In order to determine that the green Foo is not equal (!=) to purple Foo I guess I need to have another property that stores the height of the node or some other property that will enable me to enable me to compare nodes. This is the property I think I need (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;
            }
        }
    }

If you wish to create the same tree I have here is the code:

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);
like image 866
Tono Nam Avatar asked Aug 28 '12 14:08

Tono Nam


People also ask

Does TreeSet remove duplicates?

Features of TreeSet is the primary concern it is widely used in remove duplicates in the data structure as follows: TreeSet implements the SortedSet interface. So, duplicate values are not allowed and will be leftovers. Objects in a TreeSet are stored in a sorted and ascending order.

How do I delete duplicates in Family Tree Builder?

To remove a duplicate person, go to the profile of the person you want to delete, then click 'view full profile' and select the 'Relations' tab. While hovering over someone in the relations tab you will see a 'broken link' icon which will allow you to remove them from that family or the entire tree.

Can tree contain duplicates?

In a Binary Search Tree (BST), all keys in left subtree of a key must be smaller and all keys in right subtree must be greater. So a Binary Search Tree by definition has distinct keys.


2 Answers

Please, check this out:

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

It may be needless to say, still. Usage:

Node.RemoveDuplicatesFromTree(root);
like image 187
Andre Calil Avatar answered Sep 21 '22 15:09

Andre Calil


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

}

Just pass the root to this recursive function; it will trim all duplicates in the same level. You do not need to create a compare Id.

like image 34
daryal Avatar answered Sep 22 '22 15:09

daryal