Im working with simple linked lists in C# and I have no idea how to add elements at the end of the list, colud anyone helpme?
namespace ConsoleApplication1
{
class Class1
{
public class Node()
{
public int Data;
public Node Next;
}
private Node FirstNode=null;
public void AddBefore(int number)
{
Node NewNode=new Node();
NewNode.Next=FirstNode;
NewNode.Data=number;
FirstNode=NewNode;
}
public void AddAfter(int number)
{
if (FirstNode==null)
{
AddBefore(number);
}
else
{
???????????????
}
}
}
}
You need to iterate through your list until you find the last node, and then add it to the end. Something like:
public void AddAfter(int number)
{
if (FirstNode==null)
{
AddBefore(number);
}
else
{
// Finding the last node
Node currentNode = FirstNode;
while (currentNode.NextNode != null)
currentNode = currentNode.NextNode;
// Constructing a new node
Node newNode = new Node();
newNode.Data = number;
newNode.Next = null;
// Adding the new node to the end
currentNode.NextNode = newNode;
}
}
else
{
Node NewNode=new Node();
NewNode.Data=number;
Node LastNode = GetLastNode();
LastNode.Next = NewNode;
}
You'll still have to implement GetLastNode or else you wont practise anything =P
The question is kind of confusing. Are you asking how to place a node at the end of the list, or as the next item in the list.
I had to do this for a homework assignment way back in the day (it was java though). If you want to always add a node to the end of the list then you also need to edit your list class to contain a head and tail of the list. This will allow you to add items to the end or beginning.
If you want to always add a node to the end then you could try editing the code so that when you add a node to the end the previous node's next node value will be set to the tail instead of null. This will always allow for you to add an item to the end of the list (which is what most add methods do unless a position is specified anyways)
In short:
Add Node tailNode = null; to Class and add a method that will get and set the next node for the Node class. Once this is done, then edit the code so that it looks something like this:
class Class1
{
public class Node()
{
public int Data;
public Node Next;
//Class to set next node
public void setNext(Node nextNode)
{
//Set next node
Next = nextNode;
}
//Get next node
public Node getNext()
{
return Next;
}
}
private Node FirstNode=null;
private Node lastNode = null;
public void AddBefore(int number)
{
Node NewNode=new Node();
NewNode.Next=FirstNode;
NewNode.Data=number;
FirstNode=NewNode;
}
public void AddAfter(int number)
{
if (FirstNode==null)
{
AddBefore(number);
}
else
{
if(FirstNode.getNext() == null)
{
//No tail. Make this node tail
lastNode = new Node();
lastNode.Data = number;
//Set first node's next to last node
FirstNode.setNext(lastNode);
}else{ //TailNode already set
//New node to be tail
Node newLastNode = new Node();
newLastNode.Data = number;
//Set the current tail node to have this node as next
lastNode.setNext(newLastNode);
//Make new last node last node
lastNode = newLastNode;
}
}
}
}
The code may be a little off (I haven't really tested it) but that is the main picture of what you are going to have to do.
Related
why extension method does not return the modified node in Insertion operations.
But It Working Fine at the time of Linked list Creation.
Extension method should return the modified Node.
What is the perfect way to do this.
IS extension method good in performance
Code follows
public class Node
{
public Object Data { get; set; }
public Node NextNode { get; set; }
}
public static class ListOperations
{
public static void CreateLinkedList(this Node node, Object data)
{
if (node.Data == null)
{
node.Data = data;
}
else
{
Node newnode = new Node();
newnode.Data = data;
Node current = new Node();
current = node;
while (current.NextNode != null)
{
current = current.NextNode;
}
current.NextNode = newnode;
node = current;
}
}
public static void InsertNode(this Node node1, Object data, int position)
{
Node newnode = new Node();
newnode.Data = data;
if (position == 1)
{
newnode.NextNode = node1;
node1 = newnode;
}
}
}
class Program
{
static void Main(string[] args)
{
Node node = new Node();
//random Singly LinkedList
node.CreateLinkedList(10);
node.CreateLinkedList(11);
node.CreateLinkedList(12);
node.CreateLinkedList(13);
node.CreateLinkedList(14);
node.CreateLinkedList(15);
node.InsertNode(20, 1);// this method does not return node value what is inserted.
}
}
There are many things wrong with your code, and we can deal with them later. But let's answer your questions first. I will be a bit literal and direct, since I can't assume why you have done it the way it is done.
why extension method does not return the modified node in Insertion operations.
Since your method doesn't return anything
But It Working Fine at the time of Linked list Creation.
Yes, since that code doesn't ever modify the this Node node parameter
Extension method should return the modified Node.
Only if you actually return any data from the method!
What is the perfect way to do this.
See below
IS extension method good in performance
Extension method compared with what? Compared with member method written similarly, there should really be no performance difference in the cases relevant to your example
Perfect way to do it:
So first things first: There is no need to write an extension method here. Why wouldn't you write a regular member method? Extensions are usually done when the class you want to add the functionality is not directly available for you to edit, typically as the code belongs to a third party
Second, you don't quite seem to understand the references and how the pass-by-value works. First let me post a better code, and then explain it
public class Node {
public object Data { get; set; }
public Node NextNode { get; set; }
public Node(object data) {
Data = data;
}
public Node AppendNode(object data) {
var newNode = new Node(data);
var current = this;
while (current.NextNode != null)
current = current.NextNode;
current.NextNode = newNode;
return newNode;
}
public Node SetFirstNode(object data) {
return new Node(data) { NextNode = this };
}
}
class Program {
static void Main(string[] args) {
var linkedList = new Node(10);
linkedList.AppendNode(11);
linkedList.AppendNode(12);
linkedList.AppendNode(13);
linkedList.AppendNode(14);
linkedList.AppendNode(15);
linkedList = linkedList.SetFirstNode(20);
}
}
The important things to notice from the perspective of your main question (why the insert did not work) is that the method SetFirstNode actually returns the newly created node and in Main, we re-assign the linkedlist as such linkedList = linkedList.SetFirstNode(20);
Now, you can actually write a static method and pass by ref the linkedlist, but that is not a good practice, in my opinion. Nevertheless, the code would look like below
public static class ListOperations {
public static void InsertNode(ref Node linkedList, object data) {
linkedList = new Node(data) { NextNode = linkedList };
}
}
Among other things to notice, I am calling the node object as linkedList, CreateLinkedList as AppendNode and InsertNode as SetFirstNode on purpose, so you can understand the code better.
Below is the same code with generic argument instead of object Data and using a proper InsertNode method
public class Node<T> {
public T Data { get; set; }
public Node<T> Next { get; set; }
public override string ToString() {
return Data.ToString();
}
public Node(T data) {
Data = data;
}
public Node<T> AppendNode(T data) {
var newNode = new Node<T>(data);
var current = this;
while (current.Next != null)
current = current.Next;
current.Next = newNode;
return newNode;
}
/// <summary>
/// Inserts a new node into the linkedlist as the desired position
/// </summary>
/// <param name="position">0-based index for the final position of new node</param>
/// <param name="newNode">The newly created node containing data</param>
/// <returns>returns the first node of the linkedlist</returns>
public Node<T> InsertNode(T data, int position, out Node<T> newNode) {
var current = this;
position--;
newNode = new Node<T>(data);
if (position < 0) {
newNode.Next = current;
return newNode;
}
for (int i = 0; i < position; ++i)
current = current.Next;
newNode.Next = current.Next;
current.Next = newNode;
return this;
}
}
class Program {
static void Main(string[] args) {
var linkedList = new Node<int>(10);
linkedList.AppendNode(11);
linkedList.AppendNode(12);
linkedList.AppendNode(13);
linkedList.AppendNode(14);
linkedList.AppendNode(15);
linkedList = linkedList.InsertNode(20, 0, out var newNode);
}
}
I am trying to delete a node from a binary tree using c#. This example only works if the node has no children. I understand how the deletion works with children, but I'm getting hung up on an issue that seems to me to be from a lack of understanding of c#:
public class Tree
{
internal class Node
{
public int Val { get; set; }
public Node Left { get; set; }
public Node Right { get; set; }
public Node(int val)
{
Val = val;
}
}
private Node root;
public void Delete(int val)
{
Node current = this.root;
Node parent = null;
while (true) {
if (val < current.Val) {
parent = current;
current = current.Left;
}
else if (val > current.Val) {
parent = current;
current = current.Right;
}
else if (val == current.Val) {
current = null;
return;
}
}
}
}
My issue is in the line where I set current = null. The way I'm intending to use this, is to use current = null to delete the current node. But it doesn't work. if I reference the current node from the parent:
parent.Right = null;
the node is properly deleted, but is obviously a pain because I need to check if the current node is the right or left child of the node. What am I missing? Thanks in advance!
You cannot do this.
The current variable is a separate variable from the parent.Left or parent.Right variables.
When you do this:
current = parent.Left;
you're copying the value of the variable, you're not linking one variable to another. You can liken this to postit notes. On one postit note you have an address, then you execute the above statement and copy the address onto another postit note. Changing the copy afterwards does not in any way or shape change the original note.
So yes, you need to keep track of which child reference variable you got current from.
I just started using c# again and now I have a strange problem with my parameters.
I tried to build a List by my self.
So I have:
class NodeList
{
public Node FirstCity { get; set; }
public Node findNode(String name)
{
//...stuff
}
}
And This:
class Node
{
public String Name {get; set;}
public Node next {get; set;}
}
So, in my project I (lets say on button click) create a new Nodelist.
(By default I have already a few nodes in it.)
Now I do this:
Node n = nodelist.findNode("test");
and then I have another class I called tool.
tool.doSomething(n , nodelist);
Now the strange thing is that, when I look at nodelist, when I call the above the list is correct. The doSomething method, doesn´t even call the nodelist but it changes it.
doSomething(n, list)
{
NodeList nl = new NodeList();
nl.Add(n);
//other stuff
}
At the point where I change the new List for some reason the other list, which is in a different class, changes too.
Can anyone please explain why and how I can fix this!?
Edit:
This is my Add Method:
Add(Node node){
node.next = null;
Node current = FirstCity;
if (current == null)
FirstCity = node;
else
{
while (current.next != null)
{
current = current.next;
}
current.next = node;
}
}
I need to show a Tree<T> hierarchy in a TreeView, differentiating between the tree nodes and the tree leaves.
The Tree object is constructed at run time and there is no knowledge of its depth. Not a binary tree.
This is the DataTree class:
public class TreeNode<T> : IEnumerable<TreeNode<T>>
{
public T Data { get; set; }
public TreeNode<T> Parent {get; set;}
public ICollection<TreeNode<T>> Children {get; set;}
.....
.....
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<TreeNode<T>> GetEnumerator()
{
yield return this;
foreach (var directChild in this.Children)
{
foreach (var anyChild in directChild)
yield return anyChild;
}
}
}
And this is the code to populate the TreeView:
public void CreateTreeView()
{
AttributesTreeView=new TreeView();
foreach(TreeNode<string> entry in NewAttTree)
{
if(entry.Children.Count>0)
{
int tn=AttributesTreeView.Nodes.Add(new TreeNode(entry.Data.ToString().Replace("|",string.Empty)));
foreach(TreeNode<string> str in entry.Children)
{
if(tn!=0)
{
int itn=AttributesTreeView.Nodes[tn].Nodes.Add(new TreeNode(str.Data.ToString()));
}
}
}
}
}
What you're doing here is taking one tree, and projecting each node in that tree into something else, while maintaining the structure of that tree. This is actually fairly simple. Simply create a lookup that maps each node to all of its children, and then go through each of your nodes, look up "yourself" and then add all of the children from the lookup to your new node:
var roots = new TreeNode<string>[] { }; //the original data to map
var lookup = roots.SelectMany(node => node)
.ToLookup(node => node.Parent, node => new
{
node,
UINode = new TreeNode(node.Data),
});
foreach (var pair in lookup.SelectMany(group => group))
foreach (var child in lookup[pair.node])
pair.UINode.Nodes.Add(child.UINode);
TreeView view = new TreeView();
foreach (var root in lookup[null]) //assume nodes with a null parent are roots
view.Nodes.Add(root.UINode);
I can think of three ways to load a subset of the DataTreeNode structure:
Filtering: create a new DataTreeNode structure from the old structure, excluding subtrees that contain unwanted leaf nodes. Load the result.
Add a property to DataTreeNode that represents the range of values in its subtrees' leaf nodes, like a Huffman tree. Then on load, check the property before adding a given DataTreeNode.
For each DataTreeNode create a TreeNode, but discard the TreeNode if its subtrees' leaf nodes don't match the required values.
Below is pseudocode for option 3, using a HashSet to look up the required leaf node values.
void LoadDataTreeNode(TreeView treeView, DataTreeNode<T> dataTreeNode, HashSet<T> hashSet)
{
treeView.Nodes.Clear();
LoadDataTreeNode(treeView.Nodes, dataTreeNode, hashSet);
}
bool LoadDataTreeNode(TreeNodeCollection treeNodes, DataTreeNode<T> dataTreeNode, HashSet<T> hashSet)
{
bool result = hashSet.Contains(dataTreeNode.Data);
if (result)
{
var treeNode = new TreeNode(dataTreeNode.Data.ToString());
// Use this treeNode if at least one of its subtrees contains
// the required leaf node values. Assume that all other
// subtrees will be discarded by the relevant recursive calls.
result = false;
foreach (var child in dataTreeNode.Children)
{
if (LoadDataTreeNode(treeNode.Nodes, child, hashSet))
{
result = true;
}
}
if (result)
{
treeNodes.Add(treeNode);
}
}
return result;
}
OK, got it.
TreeNode newNode=new TreeNode("SEARCH");
AttributesTreeView.Nodes.Add(newNode);
CreateTreeView(NewAttTree,newNode);
public void CreateTreeView(DataTreeNode<string> root, TreeNode parentNode)
{
foreach(DataTreeNode<string> node in root.Children)
{
try
{
TreeNode newNode=new TreeNode(node.Data.ToString());
parentNode.Nodes.Add(newNode);
CreateTreeView(node,newNode);
}
catch (System.Exception e)
{
}
}
#groverboy: thanks for the push in the right direction.
One more question which presents itself:
How can we scan the DataTree structure and populate the TreeView only with the nodes that have leaves of certain value[s]. I mean in a DFT traversal, how can we decide to add a node before visiting the leaves and deciding if and which fit the filter criteria?
#groverboy: I tried your method but it didn't work and I noticed it won't ever get past the first if clause, unless the root DataTreeNode fits the bill, otherwise it returns without iterating the data tree at all.
Here is the method I came up with, based on your code: it works, but adds the same branch multiple times and I must be blind but I cant see why; maybe another pair of eyes.
bool PopulateTreeNode(DataTreeNode<string> dataNode,TreeNode treeNodes,string filter,bool ignoreCase)
{
if(dataNode.IsLeaf)
{
if(WcMatchExtensionMethods.WcMatches(dataNode.Data,filter,ignoreCase))
{
treeNodes.Nodes.Add(new TreeNode(dataNode.Data.ToString()));
return true;
}
else
return false;
}
bool result = false;
TreeNode treeNode=new TreeNode(dataNode.Data.ToString());
foreach (DataTreeNode<string> child in dataNode.Children)
{
if(PopulateTreeNode(child,treeNode,filter,ignoreCase))
{
treeNodes.Nodes.Add(treeNode);
result = true;
}
}
return result;
}
I have a N-Ary non sorted in any way tree and each node can have 0-N children. Given the data structure below, how can I fill the tree view assuming you have an array of TermNodes and that array is the first level of the TreeView? I have not been able to come up with a recursive way to do this.
class TermNode
{
public string Name;
public string Definition;
public List<TermNode> Children
}
Here is a bit of code to get you started with the recursion. It's not tested (I can't right now), but you should get the idea:
public static void BuildTreeView(TreeNodeCollection Parent, List<TermNode> TermNodeList)
{
foreach (TermNode n in TermNodeList)
{
TreeNode CurrentNode = Parent.Add(n.Name);
// no need to recurse on empty list
if (n.List.Count > 0) BuildTreeView(CurrentNode.Nodes, n.List);
}
}
// initial call
List<TermNode> AllTermNodes = /* all your nodes at root level */;
BuildTreeView(treeView1.Nodes, AllTermNodes);
Just took out Generics for a spin.. Worked nicely. Worth a look at...
public interface INode<T>
{
List<T> Children { get; }
}
class TermNode:INode<TermNode>
{
public string Name;
public string Definition;
public List<TermNode> Children { get; set; }
public TermNode()
{
this.Children = new List<TermNode>();
}
}
public class TreeBuilder<T> where T : INode<T>
{
public Func<T, TreeNode> obCreateNodeFunc;
public void AddNode(TreeView obTreeView, T obNodeToAdd, TreeNode obParentNodeIfAny)
{
TreeNodeCollection obNodes;
if (obParentNodeIfAny == null)
{
obNodes = obTreeView.Nodes;
}
else
{
obNodes = obParentNodeIfAny.Nodes;
}
int iNewNodeIndex = obNodes.Add(obCreateNodeFunc(obNodeToAdd));
TreeNode obNewNode = obNodes[iNewNodeIndex];
foreach (T child in obNodeToAdd.Children)
{
AddNode(obTreeView, child, obNewNode);
}
}
}
// calling code - Some class
static TreeNode GetTreeNodeFor(TermNode t)
{
return new TreeNode(t.Name); // or any logic that returns corr TreeNode for T
}
void Main()...
{
TermNode[] arrNodesList;
// populate list with nodes
TreeBuilder<TermNode> tb = new TreeBuilder<TermNode>();
tb.obCreateNodeFunc = GetTreeNodeFor;
foreach (TermNode obNode in arrNodesList)
{
tb.AddNode(treeView, obNode, null);
}
}
Thanks All I was getting confused because I did not realize that for a given TreeNode tn, tn.Nodes.Add would return the added TreeNode
Once you know that the solution is straight forward like so
private void /*TreeNode*/ RecursiveAdd(OntologyNode on, TreeNode tn)
{
if (on.Children.Count == 0)
{
return;
}
foreach (OntologyNode child in on.Children)
{
TreeNode tCur = tn.Nodes.Add(child.Name);
tCur.Tag = child;//optional for some selected node events
RecursiveAdd(child, tCur);
}
}
and to start of the recursive call
foreach( OntologyNode on in Nodes )
{
if (on.IsTopLevelNode == true)// internal not pertinent to this code snippet
{
TreeNode tn = tvOntoBrowser.Nodes.Add(on.Name);
tn.Tag = on;
if (on.Children.Count > 0)
{
RecursiveAdd(on, tn);
}
}
}