I want to clone a tree of objects, where every node also references the parent node:
How do I avoid cloning parents more than once at a time? Every node is a Guy. When I clone the root guy who has no parent, I clone its children and children's children. The children's parent mustn't be cloned a second time because I've cloned it already. So what cloning technique do I use? And how does it avoid my dilemma?
public class Guy
{
private Guy parent = null;
private List<Guy> children = new List<Guy>();
private double x, y, z;
}
Thanks for any useful advise!
(If the question is duplicate and you let me know, I will delete it, no problem.)
To my understanding, the cloning can be done with the following recursive function.
public Guy Clone(Guy original, Guy parent = null)
{
Guy originalClone = new Guy();
originalClone.parent = parent;
foreach (Guy child in original.children)
{
originalClone.children.Add(Clone(child,originalClone));
}
return originalClone;
}
A root to the copy of the tree is returned by the following call.
Guy RootOfCopy = Clone(RootOfOriginal);
Related
I'm having trouble trying to delete a item inside a tree structured object.
My object is as below
TreeNode
{
string name;
ObservableCollection<TreeNode> Children;
}
I thought if I recursively process through the tree and find my node and delete it but I ran into trouble.
I did something along the lines of
Updated:
DeleteNode(ObservableCollection<TreeNode> children, TreeNode nodetodelete)
{
if(children.remove(nodetodelete))
{
return;
}
else
{
foreach(var child in children)
{
DeleteNode(child, nodetodelete);
}
}
}
I realize while I was writing the code that I would eventually run into manipulation exception while iterating through a collection that has a chance of being changed.
I could build a giant change of for loops since I know exactly the max deep length(which I did for a place holder) but that seems really bad. . . .
Can anyone point me in a better general direction. I kind of wonder if my data structure is the cause of this.
Update:
This will look awful and kinda of code smell but I got the recursion to "work"
by throw a exception when I find my node.
DeleteNode(children, nodetodelete)
{
if(children.remove(nodetodelete)
{
throw FoundException();
}
else
{
foreach(var child in children)
{
DeleteNode(child, nodetodelete)
}
}
}
Is there any other way of breaking out of a recursion.
I would deal with this by making a small change to my design (assuming the snippet in your question is pseudocode for a class):
TreeNode
{
string name;
TreeNode Parent;
ObservableCollection<TreeNode> Children;
public void Delete()
{
Parent.Children.Remove(this);
}
}
This makes a little bit more work for you maintaining an extra reference when manipulating your object graph, but saves you a lot of effort and code when doing things like deletes as you can see above.
You haven't shown how you're constructing TreeNodes, but I'd make the parent and a collection for the children arguments of the constructor.
You can safely iterate over the collection of children nodes and remove them, as long as you don't change the original collection. This can be done by creating an array of the collection and iterating over that instead.
DeleteNode(ObservableCollection<TreeNode> children, TreeNode nodetodelete)
{
if (children.remove(nodetodelete))
{
return;
}
else
{
foreach (var child in children.ToArray())
{
// If anything is deleted in the collection, it will not break the iteration here, as we are iterating over an Array and not "children"
DeleteNode(child, nodetodelete);
}
}
}
This will create a new collection for you to iterate over. If a child node is deleted from children, the foreach loop will not throw an exception. That is because the original collection was changed, while we iterate over a secondary collection.
I want to store an organisation chart in a collection. I think a tree data structure will be best suited to my needs, as I need to add multiple nodes to one node.
LinkedList only provides adding one node to another node, if I understand it correctly.
I have looked at C5 treeset collection, but it doesn't seem to have Add() method to add more than 2 nodes to one node.
I have also looked at Treeview class from Windows Forms library, but I do not want to add Windows forms dll to my project, since I am building a service layer application. (or is it fine?)
I do not want to write my own tree collection class, if there is already one provided by 3rd party?
Any suggestion please?
Thanks
Something like this can be a starting point. By using generics this one can hold a tree of anything
class TreeNode<T>
{
List<TreeNode<T>> Children = new List<TreeNode<T>>();
T Item {get;set;}
public TreeNode (T item)
{
Item = item;
}
public TreeNode<T> AddChild(T item)
{
TreeNode<T> nodeItem = new TreeNode<T>(item);
Children.Add(nodeItem);
return nodeItem;
}
}
A sample which holds a tree of strings
string root = "root";
TreeNode<string> myTreeRoot = new TreeNode<string>(root);
var first = myTreeRoot.AddChild("first child");
var second = myTreeRoot.AddChild("second child");
var grandChild = first.AddChild("first child's child");
I want to store an organisation chart in a collection. I think a tree data structure will be best suited to my needs, as I need to add multiple nodes to one node.
LinkedList only provides adding one node to another node, if I understand it correctly.
I have looked at C5 treeset collection, but it doesn't seem to have Add() method to add more than 2 nodes to one node.
I have also looked at Treeview class from Windows Forms library, but I do not want to add Windows forms dll to my project, since I am building a service layer application. (or is it fine?)
I do not want to write my own tree collection class, if there is already one provided by 3rd party?
Any suggestion please?
Thanks
Something like this can be a starting point. By using generics this one can hold a tree of anything
class TreeNode<T>
{
List<TreeNode<T>> Children = new List<TreeNode<T>>();
T Item {get;set;}
public TreeNode (T item)
{
Item = item;
}
public TreeNode<T> AddChild(T item)
{
TreeNode<T> nodeItem = new TreeNode<T>(item);
Children.Add(nodeItem);
return nodeItem;
}
}
A sample which holds a tree of strings
string root = "root";
TreeNode<string> myTreeRoot = new TreeNode<string>(root);
var first = myTreeRoot.AddChild("first child");
var second = myTreeRoot.AddChild("second child");
var grandChild = first.AddChild("first child's child");
Sometimes you get one of those days no matter how much you batter your head around a wall, even the simplest task alludes you (this is one of those days!).
So what I have is a list of categories
CategoryID, CategoryName, ParentID, Lineage
1 Root Category, NULL, /1/
2 Child Category, 1, /1/2/
3 Grandchild, 2, /1/2/3
4 Second Root, NULL, /4/
5 Second Child 2, /1/2/5/
I've created a class to hold this where it contains all the values above, plus
ICollection<Category> Children;
This should create the tree
Root Category
`-- Child category
| `-- Grandchild
`-- Second Child
Second Root
So I'm trying to add a new category to the tree given the Lineage and the element, I convert the lineage to a queue and throw it into this function.
public void AddToTree(ref Category parentCategory, Category newCategory, Queue<Guid>lineage)
{
Guid lastNode = lineage.Dequeue();
if(lastNode == newCategory.CategoryId)
{
parentCategory.Children.Add(newCategory);
return;
}
foreach (var category in parentCategory.Children)
{
if(category.CategoryId == lastNode)
{
this.AddToTree(ref category, newCategory, lineage);
}
}
}
Now two problems I'm getting
The self referencing isn't too worrying (its designed to be recursive) but since the category in the foreach loop is a locally instantiated variable I can't make it by reference and use it as a pointer.
I'm sure there has to be an easier way than this!
Any pointers would be greatly received.
This code seems to be what you are looking for, but without any self references and recursions - it goes through the tree along the given lineage and in the end of the lineage inserts the given category.
Several assumptions:
Tree is stored as a list of its roots
lineage is a string
void AddCategory(List<Category> roots, Category categoryToAdd, string lineage)
{
List<Guid> categoryIdList = lineage.Split('/').Select(id => new Guid(id)).ToList();
List<Category> currentNodes = roots;
Category parentNode = null;
foreach (Guid categoryId in categoryIdList)
{
parentNode = currentNodes.Where(category => category.CategoryId == categoryId).Single();
currentNodes = parentNode.Children;
}
parentNode.Children.Add(categoryToAdd);
}
You dont appear to need the "ref" at all. You are not modifying the object reference, just its state.
EDIT:
If you must use ref, then use a temporary variable, for example...
foreach (var temp in parentCategory.Children)
{
Category category = temp;
if (category.CategoryId == lastNode)
{
this.AddToTree(ref category, newCategory, lineage);
}
}
But even with this, the ref is about useless. AddToTree does not modify the reference value. It modifies the referenced objects state. Maybe you have more code involved that we need to see.
If your intent is to modify the child reference in the parent, you will have an issue with ICollection Children object. You cannot use "ref" on an element in the ICollection to in effect replace the reference. You would have to remove the child reference and add a new one.
I'm facing a real problem in understanding how to draw a variable diagram to a linked list
In the book I'm reading its not giving enough info
I will post an example:
the insert:
public void Insert(Object newItem, Object after)
{
Node current = new Node();
Node newNode = new Node(newItem);
current = Find(after);
newNode.Link = current.Link;
current.Link = newNode;
}
private Node FindPrevious(Object n)
{
Node current = header;
while(!(current.Link == null) && (current.Link.Element != n))
current = current.Link;
return current;
}
public void Remove(Object n)
{
Node p = FindPrevious(n);
if (!(p.Link == null))
p.Link = p.Link.Link;
}
I've searched the net for more info but each time I found different info can anyone help please
Are you trying to draw it out on paper for homework? If so, the Link property of each node has a reference to the next node in the linked list. To draw it, you would probably have a series of boxes in a row that represent the node classes. In each node, you would have two properties, the Item and the Link. Link would point to the next node in the chain and Item would point to the item outside the list.
The code you provide looks like a singly linked list. See the Wikipedia page on linked lists for an example and a simple diagram. In that example, the numbers are the data in the linked list (your items) and the dots with the arrows are your links to the next item in the list (the Link property.)
Hope this is what your looking for. Otherwise, please revise your question.
First of all, you will need to know the basics of drawing.
A good idea would be to provide a separated "DrawNode" function. Then, you will need to retrieve the Node's children, and draw each of them. Finally, you'll need to draw the links.
Make sure one drawn node is not hiding another.
I hope this helps. If not, please specify what you don't understand.