C# Linked-list can't understand add method - c#

Can't understand how Head is getting the data that is passed to curr. Would be great if somebody gave a clear explanation
class LinkedListService
{
private Service Head;
public LinkedListService()
{
Head = null;
}
public void add(Service data)
{
Service curr = Head;
if (Head == null)
{
Head = data;
}
else
{
while (curr.Next != null)
{
curr = curr.Next;
}
curr.Next = data; // how does Head receive the data that is passed to curr ?
}
}
}

curr.Next = data; // how does Head receive the data that is passed to curr ?
It doesn't. In the first line curr is pointed towards the object Head.
Service curr = Head; // curr --> Head
now if Head is not initialized yet, meaning : if (Head == null) it will take the data and point Head to the same address in memory where data exist in this line:
Head = data;
If on the other hand the Head already exists than the new data has to go to the end of the tail. The tail is represented as a series of elements which are accessible through the Next property:
Head | Head.Next --> item2 | item2.Next --> item3 | item3.Next --> null
The last item in the tail will have no next item. So it's value will be null. The while loop runs through the entire tail as long as there exist a Next element and at each step assigns the Next element to the current element:
while (curr.Next != null)
{
curr = curr.Next;
}
Whe it has reached the last element which has no Next item it will take the Next property and point it towards the memory address where data is situated:
curr.Next = data;
No you have one more Item in the list at the end. And again this new item has the Next property pointing to null.
Hope it is understandable. If not drop me a comment.

Related

Adding in Sorted Linked List in C#

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

Getter and Setter c#

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>.

Adding elements to an ordered list

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

Working with lists in C#

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

Non-recursive post order traversal

I saw the following post order traversal algorithm in some website... it seems to be correct. I just want to verify that this algorithm works correctly — is this algorithm correct for post order traversal without recursion?
void postOrderTraversal(Tree *root)
{
node * previous = null;
node * s = null;
push(root);
while( stack is not empty )
{
s = pop();
if(s->right == null and s->left == null)
{
previous = s;
process s;
}
else
{
if(s->right == previous or s->left == previous)
{
previous = s;
process s;
}
else
{
push( s );
if(s->right) { push(s->right); }
if(s->left) { push(s->left); }
}
}
}
}
Try to write iterative versions of pre-order, in-order, and post-order binary traversal methods. You will then see the pattern or methodology of converting their corresponding recursive versions into the iterative versions.
Key point is sticking to some basic rules:
- Use node selection (e.g., currentNode = currentNode->Left before reiterating the loop, etc.) for immediate node traversal.
- Use stack to remember nodes that need to be visited or revisited later.
- If a node need to be "REvisited," detecting / keeping the state so that you can indicate whether the next node needs to be "processed" in next iteration or one of more of the child nodes should be visited before the node can be processed.
If you stick to these rules, you can esily accomplish the tasks.
Here is an example of the iterative post-order traversal. Ignore BinarySearchTree - it works for any binary trees.
public static IEnumerator<BinarySearchTreeNode<T>> GetPostOrderTraverseEnumerator(BinarySearchTreeNode<T> root)
{
if (root == null)
{
throw new ArgumentNullException("root");
}
Stack<BinarySearchTreeNode<T>> stack = new Stack<BinarySearchTreeNode<T>>();
BinarySearchTreeNode<T> currentNode = root;
// If the following flag is false, we need to visit the child nodes first
// before we process the node.
bool processNode = false;
while (true)
{
// See if we need to visit child nodes first
if (processNode != true)
{
if (currentNode.Left != null)
{
// Remember to visit the current node later
stack.Push(currentNode);
if (currentNode.Right != null)
{
// Remember to visit the right child node later
stack.Push(currentNode.Right);
}
// Visit the left child
currentNode = currentNode.Left;
continue;
}
else if (currentNode.Right != null)
{
// Remember to visit the current node later
stack.Push(currentNode);
// Visit the right child
currentNode = currentNode.Right;
continue;
}
}
// Process current node
yield return currentNode;
// See if we are done.
if (stack.Count == 0)
{
break;
}
// Get next node to visit from the stack
BinarySearchTreeNode<T> previousNode = currentNode;
currentNode = stack.Pop();
// See if the next node should be processed or not
// This can be determined by the fact that either of the current node's child nodes
// has just been processed now.
processNode = (previousNode == currentNode.Left || previousNode == currentNode.Right);
}
}
no here prev should not start with null
eg:for bst having nodes 5 2 1 3 7 6 8 0
it will not consider zero because at 1 its right is null and this time previous will also be null hence it will not consider its left child i.e. 0
write previous=any value but not null
Here is the working code
Stack s=new Stack();
while(true){
if(root!=null){
s.push(root);
root=root.left;
}
else{
if(s.top().right==NULL){
root=s.top();
s.pop();
System.out.println(root.data);
if(root==s.top().right){
System.out.println(s.top().data);
s.pop();
}
}
if(!s.empty())
root=s.top().right;
else
root=NULL;
}
}

Categories