C# - LinkedList - How to remove all nodes after specified node? - c#

I am implementing an undo/redo buffer with generic LinkedList.
In this state:
[Top]
state4 (undone)
state3 (undone)
state2 <-- current state
state1
[bottom]
When I do a Push, I would like to remove all states after the current one, and push the new one.
My current bypass is to do while (currentState != list.last), list.removeLast(); but it sucks
LinkedList just support Remove, RemoveFirst & removeLast...
I would like something like RemoveAllNodesAfter(LinkedListNode ...) ?
How can I code that nicely, without iterating throught all nodes ? Maybe with extensions ?...

I can't see anything in the standard LinkedList<T> which lets you do this. You could look in PowerCollections and the C5 collections if you want - or just roll your own LinkedList type. It's one of the simpler collections to implement, especially if you can add functionality in a "just in time" manner.

If I were to implement this myself, I would chose a different way to implement this.
Instead of the .RemoveAllNodesAfter(node) method, I would opt to make a .SplitAfter(node) method that returned a new linked list starting with the next node after node. This would make a handier tool than just being able to chop off the tail. If you wanted your RemoveAllNodesAfter method, it would just have to call the SplitAfter method internally and discard the result.
Naive implementation:
public LinkedList<T> SplitAfter(Node node)
{
Node nextNode = node.Next;
// break the chain
node.Next = null;
nextNode.Previous = null;
return new LinkedList<T>(nextNode);
}
public void RemoveAllNodesAfter(Node node)
{
SplitAfter(node);
}

Linked List (especially the singly linked list) is one of the most basic fundamental collection structures. I'm certain that you could probably implement it (and add the behavior your need) with little effort.
In reality, you don't actually need a collection class to manage the list. You could manage the nodes without a collection class.
public class SingleLinkedListNode<T>
{
private readonly T value;
private SingleLinkedListNode<T> next;
public SingleLinkedListNode(T value, SingleLinkedListNode<T> next)
{
this.value = value;
}
public SingleLinkedListNode(T value, SingleLinkedListNode<T> next)
: this(value)
{
this.next = next;
}
public SingleLinkedListNode<T> Next
{
get { return next; }
set { next = value; }
}
public T Value
{
get { return value; }
}
}
If you're interested in a possible implementation, however, here's a somewhat simple SingleLinkedList implementation.
public class SingleLinkedList<T>
{
private SingleLinkedListNode<T> head;
private SingleLinkedListNode<T> tail;
public SingleLinkedListNode<T> Head
{
get { return head; }
set { head = value; }
}
public IEnumerable<SingleLinkedListNode<T>> Nodes
{
get
{
SingleLinkedListNode<T> current = head;
while (current != null)
{
yield return current;
current = current.Next;
}
}
}
public SingleLinkedListNode<T> AddToTail(T value)
{
if (head == null) return createNewHead(value);
if (tail == null) tail = findTail();
SingleLinkedListNode<T> newNode = new SingleLinkedListNode<T>(value, null);
tail.Next = newNode;
return newNode;
}
public SingleLinkedListNode<T> InsertAtHead(T value)
{
if (head == null) return createNewHead(value);
SingleLinkedListNode<T> oldHead = Head;
SingleLinkedListNode<T> newNode = new SingleLinkedListNode<T>(value, oldHead);
head = newNode;
return newNode;
}
public SingleLinkedListNode<T> InsertBefore(T value, SingleLinkedListNode<T> toInsertBefore)
{
if (head == null) throw new InvalidOperationException("you cannot insert on an empty list.");
if (head == toInsertBefore) return InsertAtHead(value);
SingleLinkedListNode<T> nodeBefore = findNodeBefore(toInsertBefore);
SingleLinkedListNode<T> toInsert = new SingleLinkedListNode<T>(value, toInsertBefore);
nodeBefore.Next = toInsert;
return toInsert;
}
public SingleLinkedListNode<T> AppendAfter(T value, SingleLinkedListNode<T> toAppendAfter)
{
SingleLinkedListNode<T> newNode = new SingleLinkedListNode<T>(value, toAppendAfter.Next);
toAppendAfter.Next = newNode;
return newNode;
}
public void TruncateBefore(SingleLinkedListNode<T> toTruncateBefore)
{
if (head == toTruncateBefore)
{
head = null;
tail = null;
return;
}
SingleLinkedListNode<T> nodeBefore = findNodeBefore(toTruncateBefore);
if (nodeBefore != null) nodeBefore.Next = null;
}
public void TruncateAfter(SingleLinkedListNode<T> toTruncateAfter)
{
toTruncateAfter.Next = null;
}
private SingleLinkedListNode<T> createNewHead(T value)
{
SingleLinkedListNode<T> newNode = new SingleLinkedListNode<T>(value, null);
head = newNode;
tail = newNode;
return newNode;
}
private SingleLinkedListNode<T> findTail()
{
if (head == null) return null;
SingleLinkedListNode<T> current = head;
while (current.Next != null)
{
current = current.Next;
}
return current;
}
private SingleLinkedListNode<T> findNodeBefore(SingleLinkedListNode<T> nodeToFindNodeBefore)
{
SingleLinkedListNode<T> current = head;
while (current != null)
{
if (current.Next != null && current.Next == nodeToFindNodeBefore) return current;
current = current.Next;
}
return null;
}
}
Now you can do this:
public static void Main(string[] args)
{
SingleLinkedList<string> list = new SingleLinkedList<string>();
list.InsertAtHead("state4");
list.AddToTail("state3");
list.AddToTail("state2");
list.AddToTail("state1");
SingleLinkedListNode<string> current = null;
foreach (SingleLinkedListNode<string> node in list.Nodes)
{
if (node.Value != "state2") continue;
current = node;
break;
}
if (current != null) list.TruncateAfter(current);
}
The thing is depending on your situation, it's not much better than this:
public static void Main(string[] args)
{
SingleLinkedListNode<string> first =
new SingleLinkedListNode<string>("state4");
first.Next = new SingleLinkedListNode<string>("state3");
SingleLinkedListNode<string> current = first.Next;
current.Next = new SingleLinkedListNode<string>("state2");
current = current.Next;
current.Next = new SingleLinkedListNode<string>("state1");
current = first;
while (current != null)
{
if (current.Value != "state2") continue;
current.Next = null;
current = current.Next;
break;
}
}
This eliminates the need for the collection class altogether.

Alternatively, you can do this:
while (currentNode.Next != null)
list.Remove(currentNode.Next);
Actually, a linked list is a fairly trivial data structure to implement especially in managed code (read: no memory management hassle).
Here's one I hacked up that support just enough functions (read: YAGNI) to support your undo/redo operations:
public class LinkedListNode<T>
{
public LinkedList<T> Parent { get; set; }
public T Value { get; set; }
public LinkedListNode<T> Next { get; set; }
public LinkedListNode<T> Previous { get; set; }
}
public class LinkedList<T> : IEnumerable<T>
{
public LinkedListNode<T> Last { get; private set; }
public LinkedListNode<T> AddLast(T value)
{
Last = (Last == null)
? new LinkedListNode<T> { Previous = null }
: Last.Next = new LinkedListNode<T> { Previous = Last };
Last.Parent = this;
Last.Value = value;
Last.Next = null;
return Last;
}
public void SevereAt(LinkedListNode<T> node)
{
if (node.Parent != this)
throw new ArgumentException("Can't severe node that isn't from the same parent list.");
node.Next.Previous = null;
node.Next = null;
Last = node;
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<T>)this).GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
var walk = Last;
while (walk != null) {
yield return walk.Value;
walk = walk.Previous;
}
}
}
Then you can use the SevereAt method in your code to "cut" the linked list nice and simple.

The first idea that springs to mind is to set Node.Next.Previous = null (if it's a doubly-linked list) and then Node.Next = null .
Unfortunately, because LinkedListNode<T>.Next and LinkedListNode<T>.Previous are read-only properties in the .NET implementation of Linked List, I think you may have to implement your own structure to achieve this functionality.
But as others have said, that should be easy enough. There are plenty of resources you can use as a starting point if you just Google for linked lists C#.

if(this.ptr != null && this.ObjectName != null)
{
LinkedListNode<ObjectType> it = ObjectName.Last;
for (; it != this.ptr; it = it.Previous)
{
this.m_ObjectName.Remove(it);
}
}
this.ptr is of type LinkedListNode<ObjectType> just fyi
this.ptr is a pointer pointing to the node you are currently at, I'm assuming you want to delete everything to the right of it.
Don't make a new copy of your structure, its the worst idea ever. It is a complete memory hog and the structure could be extremely large. Copying the Object is not good programming practice unless its absolutely necessary. Try to do in-place operations.

I've made two extension methods for "removing all nodes before specific node" and "removing all nodes after specific node". However, these extension methods are extensions of LinkedListNode, not LinkedList itself, just for convenience:
public static class Extensions
{
public static void RemoveAllBefore<T>(this LinkedListNode<T> node)
{
while (node.Previous != null) node.List.Remove(node.Previous);
}
public static void RemoveAllAfter<T>(this LinkedListNode<T> node)
{
while (node.Next != null) node.List.Remove(node.Previous);
}
}
Example of use:
void Main()
{
//create linked list and fill it up with some values
LinkedList<int> list = new LinkedList<int>();
for(int i=0;i<10;i++) list.AddLast(i);
//pick some node from the list (here it is node with value 3)
LinkedListNode<int> node = list.First.Next.Next.Next;
//now for the trick
node.RemoveAllBefore();
//or
node.RemoveAllAfter();
}
Well it's not the most effective approach and if you find yourself calling this method on large lists or very often, then other here described approaches are probably more fit (like writing your own linked list class which allows splitting as described in other answers) but if it is just occassional "remove node here and there" than this is simple and quite intuitive.

Related

How can i implement a pop method for a generic stack without traversing the list

I have a generic stack that I will use in a console application. I need the stack to behave like a .Net stack but with extra functionality. Below is part of the code for the stack
class DynamicGenericStack<T>
{
private class Node
{
public T element { get; private set; }
public Node Next { get; set; }
public Node(T element, Node prevNode)
{
this.element = element;
Next = null;
Previous = null;
if (prevNode != null) //if this is not the first node
prevNode.Next = this;
}
}
private Node head, tail;
public int Count { get; private set; } //Count
public DynamicStack()
{
this.head = null;
this.tail = null;
this.Count = 0;
}
public void Push(T item)
{
if (this.head == null)
this.head = this.tail = new Node(item, null);
else
tail = new Node(item, tail);
Count++;
} Push
public T Peek()
{
return tail.element;
} Peek
public T Pop()
{
if (Count > 0)
{
T item = tail.element;
Node prev = null, current = head;
while (current != tail)
{
prev = current;
current = current.Next;
}
tail = prev;
Count--;
return item;
}
return default(T);
}
}
How can I implement the pop method above to remove the tail node without having to traverse the entire list as I did in the above code using the while loop? Is there any way in which track the tail node and remove it directly?
A single linked list is good enough for a stack, and only a head reference is needed.
To push onto the stack:
create new_node
new_node.next = head;
head = new_node;
count++;
To pop from the stack:
if(count == 0)
return null;
tmp_node = head;
head = head.next;
count--;
return tmp_node.element;
In a stack you are not really interested in the bottom. You have three main methods:
push: adds a new item over the top
pop: removes the top
top: reads the top
Change 1: next -> prev
You will need to always track what the top is and therefore you will need to know what are the previous elements.
public Node Prev { get; set; }
Change 2: Apply the same idea for Node constructor
public Node(T element, Node prevNode)
{
this.element = element;
Next = null;
Previous = null;
if (prevNode != null) //if this is not the first node
prevNode.Prev = this;
}
Change 3: Apply this logic at Pop
public T Pop()
{
T element = default(T);
if (Count > 0)
{
element = tail.element;
if (tail.Prev != null) {
tail = tail.Prev;
} else {
head = tail = null;
}
}
return element;
}

AddFront in LinkedList with tail and reference to previous node from the tail (tail.Previous)

Could you please help to understand, how I can modify AddFront method in LinkedList and set a tail and reference to the previous node (for example tail.Previous)? The tail should point out the first added element (last element in the LinkedList) and tail.Previous to second added element (second element from the end) and be able to access elements from tail to the head using Previous property.
Thanks.
public class Node
{
public int Data;
public Node Next;
public Node Previous;
public Node(int x)
{
Data = x;
Next = null;
Previous = null;
}
public class MyLinkedList
{
private int Length { get; set; }
private Node head = null;
private Node tail = null;
public void AddFront(int x)
{
var newNode = new Node(x);
newNode.Next = head;
if (head != null)
{
head.Previous = newNode;
}
//Somewhere here tail and tail.Previous should be set
head = newNode;
Length++;
}
}
Just add the else case:
if (head != null)
{
head.Previous = newNode;
}
else
{
tail = newNode;
}

Remove operation in c# linked list

I have a problem concerning c# remove operation in linked list. LinkedListNode<T> is immutable, but Remove(LinkedListNode<T>) is constant time. Why do I have a problem with it? Here is the reason:
Normally, when removing I would write the following code (forget about nulls):
public void Remove(LinkedListNode<T> node)
{
node.Previous.Next = node.Next;
node.Next.Previous = node.Previous;
}
But since LinkedListNode<T> is immutable, this is not an option. How is it done in O(1) time then?
It isn't immutable but those properties are read-only properties:
//Out of LinkListNode<T>:
public LinkedListNode<T> Next {
get { return next == null || next == list.head? null: next;} //No setters
}
public LinkedListNode<T> Previous {
get { return prev == null || this == list.head? null: prev;} //No setters
}
That is why you can't assign them.
Instead of implementing it yourself use LinkedList<T>.Remove() method:
LinkedList<int> list = new LinkedList<int>(new int[] { 1, 2, 3, 4 });
list.Remove(3);
// list: 1,2,4
If you look under Reference Source you will see the implementation as:'
public bool Remove(T value) {
LinkedListNode<T> node = Find(value);
if (node != null) {
InternalRemoveNode(node); // <==============
return true;
}
return false;
}
public void Remove(LinkedListNode<T> node) {
ValidateNode(node);
InternalRemoveNode(node); // <==============
}
internal void InternalRemoveNode(LinkedListNode<T> node) {
Debug.Assert( node.list == this, "Deleting the node from another list!");
Debug.Assert( head != null, "This method shouldn't be called on empty list!");
if ( node.next == node) {
Debug.Assert(count == 1 && head == node, "this should only be true for a list with only one node");
head = null;
}
else {
/******************** Relevant part here *****************/
node.next.prev = node.prev;
node.prev.next = node.next;
if ( head == node) {
head = node.next;
}
}
node.Invalidate();
count--;
version++;
}
So basically they implemented it as you wanted too but they can use different variables which are internal and are not read-only:
internal LinkedListNode<T> next;
internal LinkedListNode<T> prev;
Internally, the method Remove of LinkedList(T) relies on:
internal void InternalRemoveNode(LinkedListNode<T> node)
which itself, in turn, directly manipulates the corresponding backing fields of LinkedListNode(T), both declared with the internal visibility as well :
internal LinkedListNode<T> prev;
and
internal LinkedListNode<T> next;
'Hope this helps,

What is the best alternative for a concurrent task queue, not using .net 4.0

I'm trying to implement a framework for working with multiple cores in Unity applications.
What I have so far is a non-blocking queue implemented by Julian M Bucknal. It seems to work very well for my purposes. I've created a task class, and a result class, and use two queues to distribute and collect the work which is processed on the secondary threads.
The remaining issue is that since this code is going to be used a lot in performance critical sections of my application, I would really like to minimize the use of the garbage collector.
Is there a known library / template / technique that could help me make this improvement?
using System.Threading;
public class LockFreeQueue<T> {
internal struct SingleLinkNode<U> where U : T {
// Note; the Next member cannot be a property since
// it participates in many CAS operations
public SingleLinkNode<U> Next;
public U Item;
}
static private bool CAS<V>(ref V location, V comparand, V newValue) where V : class {
return
(object) comparand ==
(object) Interlocked.CompareExchange<V>(ref location, newValue, comparand);
}
SingleLinkNode<T> head;
SingleLinkNode<T> tail;
public LockFreeQueue() {
head = new SingleLinkNode<T>();
tail = head;
}
public void Enqueue(T item) {
SingleLinkNode<T> oldTail = null;
SingleLinkNode<T> oldTailNext;
SingleLinkNode<T> newNode = new SingleLinkNode<T>();
newNode.Item = item;
bool newNodeWasAdded = false;
while (!newNodeWasAdded) {
oldTail = tail;
oldTailNext = oldTail.Next;
if (tail == oldTail) {
if (oldTailNext == null)
newNodeWasAdded = CAS<SingleLinkNode<T>>(ref tail.Next, null, newNode);
else
CAS<SingleLinkNode<T>>(ref tail, oldTail, oldTailNext);
}
}
CAS<SingleLinkNode<T>>(ref tail, oldTail, newNode);
}
public bool Dequeue(out T item) {
item = default(T);
SingleLinkNode<T> oldHead = null;
bool haveAdvancedHead = false;
while (!haveAdvancedHead) {
oldHead = head;
SingleLinkNode<T> oldTail = tail;
SingleLinkNode<T> oldHeadNext = oldHead.Next;
if (oldHead == head) {
if (oldHead == oldTail) {
if (oldHeadNext == null) {
return false;
}
CAS<SingleLinkNode<T>>(ref tail, oldTail, oldHeadNext);
} else {
item = oldHeadNext.Item;
haveAdvancedHead = CAS<SingleLinkNode<T>>(ref head, oldHead, oldHeadNext);
}
}
}
return true;
}
public T Dequeue() {
T result;
Dequeue(out result);
return result;
}
}
I managed to minimize the garbage collection by reusing instances of SingleLinkNode<T>.
Here's my customized non-blocking stack:
using System.Threading;
public class LockFreeLinkPool<T> {
private SingleLinkNode<T> head;
public LockFreeLinkPool() {
head = new SingleLinkNode<T>();
}
public void Push(SingleLinkNode<T> newNode) {
newNode.Item = default(T);
do {
newNode.Next = head.Next;
} while (!SyncMethods.CAS<SingleLinkNode<T>>(ref head.Next, newNode.Next, newNode));
return;
}
public bool Pop(out SingleLinkNode<T> node) {
do {
node = head.Next;
if (node == null) {
return false;
}
} while (!SyncMethods.CAS<SingleLinkNode<T>>(ref head.Next, node, node.Next));
return true;
}
}
I carefully clean all the instances SingleLinkNode before and after storage. This has some very cool implications for our usage of threads in Unity.

Insertion At last Node Single Linked List

i am working on linked list.. i successfully inserted and deleted a node at first node.. but when i try to insert node at last .. it gives an error "Object reference not set to an instance of an object"
My logic is correct but visual studio is generating an exception dont know why
please help me out..
Full code is given below
class MyList
{
private Node first;
private Node current;
private Node previous;
public MyList()
{
first = null;
current = null;
previous = null;
}
public void InsertLast(int data)
{
Node newNode = new Node(data);
current = first;
while (current != null)
{
previous = current;
current = current.next;
}
previous.next = newNode;
newNode.next = null;
}
public void displayList()
{
Console.WriteLine("List (First --> Last): ");
Node current = first;
while (current != null)
{
current.DisplayNode();
current = current.next;
}
Console.WriteLine(" ");
}
}
class Node
{
public int info;
public Node next;
public Node(int a)
{
info = a;
}
public void DisplayNode()
{
Console.WriteLine(info);
}
}
class Program
{
static void Main(string[] args)
{
MyList newList = new MyList();
newList.InsertLast(10);
newList.InsertLast(20);
newList.InsertLast(30);
newList.InsertLast(40);
newList.displayList();
Console.ReadLine();
}
}
Basically you will have to deal with the case of an empty list. In your current code when the list is empty you have previous, current, and first all equal to null. So you're getting an error because you're attempting to assign previous.next() a value when previous equals null.
If the list is empty, first will be equal to null and your code will raise exception when you try to do this previous.next = newNode; because the previous is also null. when adding first node, you will have to add the new element as first, so rewrite the code like this:
public void InsertLast(int data)
{
Node newNode = new Node(data);
if (first == null)
{
first = newNode;
}
else
{
current = first;
while (current != null)
{
previous = current;
current = current.next;
}
previous.next = newNode;
}
newNode.next = null;
}
EDIT: You can implement it something like this but take care if the fist is null and the case when there is only first node. Check the method:
public void RemoveLast()
{
if (first != null)//there is no point in removing since the list is empty
{
if (first.next == null) //situation where list contains only one node
first = null;
else //all other situations
{
current = first;
while (current.next != null)
{
previous = current;
current = current.next;
}
previous.next = null;
}
}
}

Categories