Im working with the code on this page Working with C# lists since 2 days, and I have a problem when I try to change the code to add items to the list after the previous item (instead before the previous item) .
//ListNode constructor params: name, code, nextNode
//Insert element after the first element
public void InsertelementAfterTheFirst(object name, object code)
{
if (IsEmpty())
FirstNode = LastNode = new ListNode(name, code, null);
else
{
FirstNode = new ListNode(name, code, FirstNode);
}
}
I know I can use the "List<>" collection in C#, but my intention is to learn how does the lists works.
Thanks for the help.
Here is the pseudo code...
if (firstNode is empty)
{
//new list...
firstNode = lastNode = new Node(name, code, null);
}
else
{
var node = new Node(name, code, firstNode.nextNode);
firstNode.nextNode = node;
}
Only thing is, this is only good for adding a node after the first Node. A better method might be to specify in the InsertAfter method which node you want to attach the new node to. Or if you are using an iterator-like pattern (your Linked List class has Current node), you can do similar thing.. just get the current node and the code in the else branch above should still work (but instead firstNode, it will be currentNode).
Something like:
public ListNode InsertAfterCurrent(object name, object code)
{
if (currentNode == null)
{
//assume new list
currentNode = firstNode = lastNode = new ListNode(name, code, null);
}
else
{
currentNode.NextNode = new ListNode(name, code, currentNode.NextNode);
}
}
public ListNode InsertAfter(ListNode anchor, object name, object code)
{
if (anchor != null && NodeIsPartOfList(anchor))
{
anchor.NextNode = new ListNode(name, code, anchor.NextNode);
}
}
public bool NodeIsPartOfList(ListNode node)
{
var current = firstNode;
while (current != null)
{
if (current == node)
return true;
current = current.NextNode;
}
return false;
}
Before I answer this I feel I should mention that posting code in Spanish on an English speaking forum is in bad taste. I spent more time trying to understand your basically gibberish naming than writing this post.
Also, List<>, despite its poor naming, isn't implemented as a list. It's a wrapper over an array, which is why .ToArray() is so efficient.
Now to your specific problem, you want to set your head link to the node you just created, and set its next link to the previous head link:
if (EsVacio())
primerNodo = ultimoNodo = new ListNode(nom, cod, null);
else
{
var node=new ListNode(nom, cod, primerNodo);
node.Siguiente=primerNodo;
primerNodo=node;
}
Related
I have such a class for implementation of Sorted Linked List in C#. Now it's not actually sorted, but what changes do I have to make to this method it become one?
class LinkedSortedList<T>
{
public Node<T> Head { get; set; }
public Node<T> Tail { get; set; }
public int Count { get; set; }
public LinkedSortedList()
{
Head = null;
Tail = null;
Count = 0;
}
public LinkedSortedList(T data)
{
CreateList(data);
}
public void AddElement(T data)
{
if (Tail != null)
{
var node = new Node<T>(data);
Tail.Next = node;
Tail = node;
Count++;
}
else
{
CreateList(data);
}
}
public void CreateList(T data)
{
var node = new Node<T>(data);
Head = node;
Tail = node;
Count = 1;
}
I want to modify AddElement function so that the list is and remains sorted. How can I implement this logic?
A key observation you need to make in order to complete the task is that at the beginning of AddElement the list is either empty, or sorted. If the list is empty, your task is trivial; if the list is sorted, you must pick an insertion point for the element being added, and insert the new element there. The list will remain sorted after the insertion, because no other elements would need to be moved.
To find the insertion point, start walking the list from the head until you either (1) find an element that is greater than the one being inserted, or (2) you reach the end of the list. In both cases you simply insert the new element immediately after the last element that you've passed during the traversal, or at the head if the initial element is greater than the one you are inserting.
Currently you're just adding elements to the end of the list. Instead, we want to walk the list and look at each value until we find the correct place to insert the node.
One way to do this is to do the following checks:
Is the Head null? If so, create a new list with this data and we're done.
Is the new node's data less than the Head data? If so, put this node in front of the Head and point the Head to our new node.
Is the new node's data greater than the Tail data? If so, put this node after the Tail and point the Tail to our new node.
Otherwise, create a "current" node that points to the head, compare the data of the current node with our new node, and continue to move through the list by setting "current" to it's Next property until we find the proper place to insert the new node. Then rearrange the Next and Previous properties of the three nodes (the new node, the one before it, and the one after it).
For example:
public void AddElement(T data)
{
if (Head == null)
{
CreateList(data);
}
else
{
var node = new Node<T>(data);
if (node.Data < Head.Data)
{
Head.Previous = node;
node.Next = Head;
Head = node;
}
else if (node.Data > Tail.Data)
{
Tail.Next = node;
node.Previous = Tail;
Tail = node;
}
else
{
var current = Head;
while(node.Data >= current.Data && current.Next != null)
{
current = current.Next;
}
node.Previous = current.Previous;
if (node.Previous != null) node.Previous.Next = node;
current.Previous = node;
node.Next = current;
if (Head == current) Head = node;
Count++;
}
}
}
I have multiple objects(nodes) and each node has a getter and setter for a list named Calea which contains other nodes, also each node has neighbours and they are also nodes . The problem is that list is stacking up and I can't figure out why , it's like a static variable and also I am not using that getter and setter anywhere else.
Here is my code :
private int cost = 10000;
private LinkedList<GraphNode<string>> calea=new LinkedList<GraphNode<string>>() ;
public int Cost
{
get
{
return cost;
}
set
{
cost = value;
}
}
public LinkedList<GraphNode<string>> Calea
{
get
{
if (calea == null) return new LinkedList<GraphNode<string>>();
return calea;
}
set
{
calea = value;
}
}
Code above shows the method for Cost and Calea , Cost works fine but Calea is stacking up.The code below is a sample of code of how I am setting the value Calea for each node:
if (curr.Neighbors.ElementAt(i).Cost > curr.Costs.ElementAt(i) + curr.Cost)
{
curr.Neighbors.ElementAt(i).Cost = curr.Costs.ElementAt(i) + curr.Cost;
curr.Neighbors.ElementAt(i).Calea = curr.Calea;
curr.Neighbors.ElementAt(i).Calea.AddLast((GraphNode<string>)curr.Neighbors.ElementAt(i));
index = i;
}
++i;
The sample code where I change the current node below:
pathNodesToVisit.Remove(curr);
if (pathNodesToVisit.Count == 0) break;
if (curr.Neighbors.Count > index)
{
for (int j = 0; j < pathNodesToVisit.Count; j++)
{
if (pathNodesToVisit.ElementAt(j).Value == curr.Neighbors.ElementAt(index).Value)
{
indexx = j;
//MessageBox.Show(pathNodesToVisit.ElementAt(j).Value);
}
}
curr = pathNodesToVisit.ElementAt(indexx);
}
else
{
curr = pathNodesToVisit.ElementAt(0);
}
A few words : pathNodesToVisit are all the nods which I want to visit(Dijkstra algorithm) , in the code above I remove the curr node from the list and the new curr node is a node which had the Costs and Calea changed.
I have no idea what you mean by "stacking up," but:
public LinkedList<GraphNode<string>> Calea
{
get
{
if (calea == null) return new LinkedList<GraphNode<string>>();
return calea;
}
... creates a new list every time the property is read, not just the first time. calea will always be null with this approach.
Try
get
{
if (null == calea)
calea = new LinkedList<GraphNode<string>>();
return calea;
}
Update
The line
curr.Neighbors.ElementAt(i).Calea = curr.Calea;
Does not make a copy of the list. It copies a reference to the list. Any changes made to any node's calea afterward will affect every node, not just the one you're after.
Try
curr.Neighbors.ElementAt(i).Calea = new LinkedList<GraphNode<string>>(curr.Calea);
Though, you should make sure .Neighbors actually has an element i before doing this, among other things.
Note: In the case of an uninitialized node, this will actually create two lists - once when Calea is read (LH of the expression, which calls your .get), and another on the right.
There are many ways to copy a collection. I suggest googling c# deep copy LinkedList<T>.
I want to add an element to a linked list so that the list remains sorted. I wrote this function. He's got a place that should be included, but I do not know how to insert the element.
public void AddSorted(int num)
{
Node n = new Node(num);
Node curr = _first;
Node curr1 = _first.Link;
while (curr1.Data < n.Data && curr1 != null)
{
curr = curr.link;
curr1= curr1.link;
}
// how to add element ???
}
You have provided absolutely no context regarding your LinkedList class, so I can only make an educated guess.
Given what I understand from the above code, after traversing to the location you want to insert the new Node, you will need to set the link of Node curr1 (which is the last Node) to the new node object.
Node temp = curr1.Link; // store next Node in temporary object
curr1.Link = n; // Insert new Node
Remember that you need to set the link of the new node to the next node in the LinkedList in order to continue the LinkedList (if the newly inserted Node is not the last):
n.Link = temp;
Please let me know if I made a mistake understanding your code, I can then change my answer accordingly.
With the help of my dear friends.
I could write this function.
Below you can see the code :
public void AddSorted(int num)
{
Node n = new Node(num);
Node curr = _first;
if (_first == null || _first.Data >= n.Data)
{
n.Link = _first;
_first = n;
}
else
{
while (curr.Link != null && curr.Link.Data < n.Data)
{
curr = curr.Link;
}
n.Link = curr.Link;
curr.Link = n;
}
I have a recursion function that builds a node list from an IEnumerable of about 2000 records. The procedure currently takes around 9 seconds to complete and has become a major performance issue. The function serves to:
a) sort the nodes hierarchically
b) calculate the depth of each node
This is a stripped down example:
public class Node
{
public string Id { get; set; }
public string ParentId { get; set; }
public int Depth { get; set; }
}
private void GetSortedList()
{
// next line pulls the nodes from the DB, not included here to simplify the example
IEnumerable<Node> ie = GetNodes();
var l = new List<Node>();
foreach (Node n in ie)
{
if (string.IsNullOrWhiteSpace(n.ParentId))
{
n.Depth = 1;
l.Add(n);
AddChildNodes(n, l, ie);
}
}
}
private void AddChildNodes(Node parent, List<Node> newNodeList, IEnumerable<Node> ie)
{
foreach (Node n in ie)
{
if (!string.IsNullOrWhiteSpace(n.ParentId) && n.ParentId == parent.Id)
{
n.Depth = parent.Depth + 1;
newNodeList.Add(n);
AddChildNodes(n, newNodeList, ie);
}
}
}
What would be the best way to rewrite this to maximize performance? I've experimented with the yield keyword but I'm not sure that will get me the result I am looking for. I've also read about using a stack but none of the examples I have found use parent IDs (they use child node lists instead), so I am a little confused on how to approach it.
Recursion is not what is causing your performance problem. The real problem is that on each recursive call to AddChildNodes, you traverse the entire list to find the children of the current parent, so your algorithm ends up being O(n^2).
To get around this, you can create a dictionary that, for each node Id, gives a list of all its children. This can be done in a single pass of the list. Then, you can start with the root Id ("") and recursively visit each of its children (i.e. a "depth first traversal"). This will visit each node exactly once. So the entire algorithm is O(n). Code is shown below.
After calling GetSortedList, the sorted result is in result. Note that you could make children and result local variables in GetSortedList and pass them as parameters to DepthFirstTraversal, if you prefer. But that unnecessarily slows down the recursive calls, since those two parameters would always have the same values on each recursive call.
You can get rid of the recursion using stacks, but the performance gain would probably not be worth it.
Dictionary<string, List<Node>> children = null;
List<Node> result = null;
private void GetSortedList()
{
var ie = data;
children = new Dictionary<string,List<Node>>();
// construct the dictionary
foreach (var n in ie)
{
if (!children.ContainsKey(n.ParentId))
{
children[n.ParentId] = new List<Node>();
}
children[n.ParentId].Add(n);
}
// Depth first traversal
result = new List<Node>();
DepthFirstTraversal("", 1);
if (result.Count() != ie.Count())
{
// If there are cycles, some nodes cannot be reached from the root,
// and therefore will not be contained in the result.
throw new Exception("Original list of nodes contains cycles");
}
}
private void DepthFirstTraversal(string parentId, int depth)
{
if (children.ContainsKey(parentId))
{
foreach (var child in children[parentId])
{
child.Depth = depth;
result.Add(child);
DepthFirstTraversal(child.Id, depth + 1);
}
}
}
public void Insert(int value)
{
if (value < Data)
{
if (LeftNode == null)
{
LeftNode = new TreeNode(value);
}
else
{
LeftNode.Insert(value);
}
}
else if (value > Data)
{
if (RightNode == null)
{
RightNode = new TreeNode(value);
}
else
{
RightNode.Insert(value);
}
}
}
I wrote method to add element in BST recursively, It checks for value to add less than or greater than and add it in its proper place, but I want to know how iterative method works? I need iterative add method for my BST.
Ok, here's an iterative version of your algorithm:
public void Insert(int value)
{
TreeNode current = this;
while (current != null)
{
if(current.Data < value)
if(current.LeftNode == null)
{ current.LeftNode = new TreeNode(value); break; }
else current = current.LeftNode;
else
if(current.RightNode == null)
{ current.RightNode = new TreeNode(value); break; }
else current = current.RightNode;
}
}
You can find a implementation in Java at wikipedia, what is very similar C# http://en.wikipedia.org/wiki/Binary_search_tree
We start at root:
Node root = m_root;
while (root != null) {
then look if the value is less os greater than root.
if (data < root.getData()) {
Now we know if we need to traverse at left or right. The logic at left and right are the same. We look if the slot is empty and if it is, we put the value at that slot.
if (root.getLeft() == null) {
root.setLeft(new TreeNode(data, null, null));
return;
}
If the slot contains a value, then we set that slot as root and continue the process.
} else {
root = root.getLeft();
}
An iterative method is one that will repeat.
Iterative method implies it will be called repeatedly.
Recursion implies the method will call itself n times, where n > 0.
Searching a binary search tree is done using a method which calls itself (recursive) until it finds the end of a branch.
To do an insert, a search is executed to find the correct place to place the node.