C# LinkedList AddAfter - c#

I am trying to implement Insertion Sort using C# in the code below. But its giving me the error that:
The LinkedList node already belongs to a LinkedList
public void Sort(ref LinkedList<int> list)
{
LinkedListNode<int> tempNode = new LinkedListNode<int>(0); //Contains zero just for initalization
for(tempNode = list.First; tempNode!=null; tempNode=tempNode.Next)
{
LinkedListNode<int> sortedListBoundary = tempNode; //Contains zero just for initalization
while (sortedListBoundary.Value < sortedListBoundary.Next.Value && sortedListBoundary.Previous!=null)
{
sortedListBoundary = sortedListBoundary.Previous;
}
list.AddAfter(tempNode, sortedListBoundary); //This line gives error
}
}
I have even tried to take that node in a temp. Delete the existing node (sortedListBoundary) and then call AddAfter(), but this time error is:
Node doesn't belong to LinkedList()
So how can I overcome this deadlock? Thanks in advance

AddAfter(node, newNode) requires 2 things, node has to belong to the list, and newNode cannot belong to a list, this is all well and good, and removing sortedListBoundary and adding it after tempNode should have worked if not for the following:
You initialize (in the for loop) tempNode = list.First and then LinkedListNode<int> sortedListBoundary = tempNode; so now sortedListBoundary = tempNode = list.First and sortedListBoundary.Previous == null because it is first, so you do not enter the if. And so, when you get to AddAfter part, sortedListBoundary = tempNode... you are trying to add a node after itself...
Edit:
Just to clarify, when you remove sortedListBoundary, because sortedListBoundary = tempNode you are also removing tempNode (as they are the same) therefor, you get the error that it is not in the list... you can't add something after something that is not in the list.
Edit 2:
You ask for a solution, the best answer I can give is to not try to place a node after itself, go over the insertion sort algorithm carefully and see where you deviate from it, here is an implementation of insertion sort:
public void Sort(ref LinkedList<int> list)
{
LinkedListNode<int> tempNode;
for(tempNode = list.First.Next; tempNode!=null; tempNode=tempNode.Next)
{
LinkedListNode<int> sortedListBoundary = tempNode.Previous;
list.Remove(tempNode);
while (sortedListBoundary != null && tempNode.Value < sortedListBoundary.Value)
{
sortedListBoundary = sortedListBoundary.Previous;
}
if(sortedListBoundary == null)
list.AddFirst(tempNode);
else
list.AddAfter(sortedListBoundary, tempNode);
}
}
It is the closest I could make it to your code, but I don't know what you where going for.

LinkedListNode<int> sortedListBoundary is of type LinkedListNode and tempNode is also of type LinkedListNode<int> LinkedList says:
public LinkedListNode<T> AddAfter(
LinkedListNode<T> node,
T value
)

Related

Unable to iterate to next ListNode, since the current node is getting overridden with the listnode.next value

This is a leetcode problem.
I saw the solution however while trying to use my own logic, I cannot iterate over to the next node.
public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
try
{
string l1NodeData = null;
string l2NodeData = null;
do
{
l1NodeData = l1NodeData + l1.val;
l1 = l1.next;
} while (l1 != null);
do
{
l2NodeData = l2NodeData + l2.val;
l2 = l2.next;
} while (l2 != null);
int sum = Convert.ToInt32(l1NodeData) + Convert.ToInt32(l2NodeData);
var sumInChar = sum.ToString().ToArray();
ListNode dummyhead = new ListNode(0);
ListNode ans = dummyhead;
for (int i = sumInChar.Length - 1; i > 0; i--)
{
ans.val = Convert.ToInt32(sumInChar[i].ToString());
ListNode tempListNode = new ListNode(Convert.ToInt32(sumInChar[i - 1].ToString()));
ans.next = tempListNode;
ans = ans.next;
//here(ans = ans.next) after assigning the next node, the data of the current node is getting overridden.
}
return ans;
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
In the above solution where I am assigning ans = ans.next, there the current node is overridden with the next node, however, I just want to move to the next node in order to iterate.
Could someone please help me on this?
In the above solution where I am assigning ans = ans.next, there the current node is overridden with the next node, however, I just want to move to the next node in order to iterate.
The assignment is to a variable. That never mutates your linked list. This way of assigning to a variable is exactly what you need to traverse a linked list. It does not modify it. In order to mutate it, you will always need to assign to a member (property) of a node, like its next property.
In the code comments you wrote:
the data of the current node is getting overridden.
No, it looks like that because you return the reference to the last node that was created in the loop. Instead you should return dummyHead.next; This way you return the first node that was created in the loop.
In comments you wrote:
...I have not made any assignment to dummyhead right, then how does data reside in that variable?
You have referenced ans to the same node as dummyHead, and you did assign to ans.next, which in the first iteration of the loop is synonymous to dummyHead.next. With those assignments to ans.next the nodes get linked to eachother.
Note that dummyHead is an extra node that is created to ease the code in the loop -- not having to make a special case for creating the real head node. After the loop that dummyHead is then ignored (it served its purpose), and the real head (that is sitting right after it) is returned.

C# LinkedList<> remove by index

Given a:
LinkedList<int> myList;
How would I remove an element at index n? I can't seem to find any methods, only ones to remove by value which is no good as this particular list can have duplicate values.
EG:
myList.removeAt(n);
Linked lists have great advantage in speed if you are adding or removing a node you have a existing reference to, but when you don't have a reference the best you can do is walk the list to the index, grab the node, then delete it.
Here is a extension method that does that process. It returns a reference to the removed node in case you want it later to insert to some other list or you are moving it's position within the list.
public static class ExtensionMethods
{
public static LinkedListNode<T> RemoveAt<T>(this LinkedList<T> list, int index)
{
LinkedListNode<T> currentNode = list.First;
for (int i = 0; i <= index && currentNode != null; i++)
{
if (i != index)
{
currentNode = currentNode.Next;
continue;
}
list.Remove(currentNode);
return currentNode;
}
throw new IndexOutOfRangeException();
}
}

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

Improving access time on SortedDictionary

I have 2 millions items in a SortedDictionary<string, MyClass>
I've done the following and takes ages, any ideas?
for(int i = 0; i<dic.Count-1; i++)
{
Debug.WriteLine(dic.ElementAt(i).Value.ToString());
}
The SortedDictionary<TKey, TValue> class does not directly support (fast) retrieval by index; it is internally implemented as a binary search tree. Consequently, every call to the LINQ Enumerable.ElementAt method you've got there creates a new enumerator that iterates each value of the sequence represented by the key-value pairs in the collection (sorted by key) from the beginning until it reaches the desired index. This means that the loop is going to have to pull something like 1 + 2 + 3 + ... + Count (roughly 2 trillion) elements before it completes, making it (atleast) quadratic in its time-complexity.
Try this instead, which should run in roughly linear time:
foreach(var myClass in dic.Values)
Debug.WriteLine(myClass);
If you really do want fast access by index (from the provided code, there doesn't seem to be any reason to indicate this), consider using a SortedList<TKey, TValue> instead. There are downsides to this choice (slower non-appending inserts and deletes) that you should evaluate.
I also notice that the loop condition is i < dic.Count - 1 rather than the more common i < dic.Count. This is either an off-by-one bug, or perhaps you intend to not consider the last value in the dictionary. In the latter case, you could maintain a local variable serving as a counter, or with LINQ:
foreach(var myClass in dic.Values.Take(dic.Count - 1))
Debug.WriteLine(myClass);
foreach might be faster, since you don't use the indexer
foreach (var value in dic.Values)
Debug.Writeline(value)
Also, as far as speed is concerned, Debug.Writeline is probably not the best option (what are you going to do with 2 million debug trace entries anyway??). Consider writing to a file, a database, etc.
EDIT Looking at reflector, finding a value in a SortedDictionry boils down to a binary search:
internal virtual Node<T> FindNode(T item)
{
int num;
for (Node<T> node = this.root; node != null; node = (num < 0) ? node.Left : node.Right)
{
num = this.comparer.Compare(item, node.Item);
if (num == 0)
{
return node;
}
}
return null;
}
The implementation of SortedDictionary's iteration seems a bit more involved:
public bool MoveNext()
{
this.tree.VersionCheck();
if (this.version != this.tree.version)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
if (this.stack.Count == 0)
{
this.current = null;
return false;
}
this.current = this.stack.Pop();
SortedSet<T>.Node item = this.reverse ? this.current.Left : this.current.Right;
SortedSet<T>.Node node2 = null;
SortedSet<T>.Node node3 = null;
while (item != null)
{
node2 = this.reverse ? item.Right : item.Left;
node3 = this.reverse ? item.Left : item.Right;
if (this.tree.IsWithinRange(item.Item))
{
this.stack.Push(item);
item = node2;
}
else
{
if ((node3 == null) || !this.tree.IsWithinRange(node3.Item))
{
item = node2;
continue;
}
item = node3;
}
}
return true;
}
It seems to maintain a stack whose top element is the smallest (or largest, depending on the direction) one, and thus always the one to be popped and returned during iteration. I haven't done any complexity analysis, but it's bound to be considerably more efficient than running a binary search each time.
Use foreach:
foreach (var pair in d)
Debug.WriteLine(pair.Value);
I bet that debug output takes more time than dictionary lookup though.

Categories