Insertion At last Node Single Linked List - c#

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

Related

Traversing a linked-list

I created a simple node class, and solution class with an insert method, a display method, along with Main. I am trying to insert 4 numbers into the linked-list and have it display the entire list. At most I am only able to have it display 2 of the numbers. The issue is most likely in my insert method. I've spent hours trying to figure out what the issue is. What could be wrong with my code?
public static Node insert(Node head, int data)
{
Node newNode = new Node(data);
if (head == null)
{
head = newNode;
}
else
{
while (head.next != null)
{
head = head.next;
}
head.next = newNode;
}
return head;
}
public static void display(Node head)
{
Node start = head;
while (start != null)
{
Console.Write(start.data + " ");
start = start.next;
}
}
static void Main(String[] args)
{
Node head = null;
int[] numbers = new int[]{2, 3, 4, 1};
for (int i = 0; i < numbers.Length; i++)
{
int data = numbers[i];
head = insert(head, data);
}
display(head);
Console.ReadLine();
}
class Node
{
public int data;
public Node next;
public Node(int d)
{
data = d;
next = null;
}
public Node() { }
}
Yes, the problem is in the insert method:
while (head.next != null)
{
// From now on you have the initial head got lost
head = head.next;
}
Quick amendment is to change while into for:
public static Node insert(Node head, int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
}
else {
// we loop on last, keeping head intact
for (Node last = head; ; last = last.next)
if (last.next == null) {
last.next = newNode;
break;
}
}
return head;
}
we can simplify it further:
public static Node insert(Node head, int data) {
Node newNode = new Node(data);
for (Node last = head; last != null; last = last.next)
if (last.next == null) {
last.next = newNode;
return head;
}
return newNode;
}

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

Object reference not set to an instance of an object- Linked List Example

I am seeing following errors :
Object reference not set to an instance of an object!
Check to determinate if the object is null before calling the method!
I made a small test program for Sorted Linked Lists.
Here is the code where the error comes!
public void Insert(double data)
{
Link newLink = new Link(data);
Link current = first;
Link previous = null;
if (first == null)
{
first = newLink;
}
else
{
while (data > current.DData && current != null)
{
previous = current;
current = current.Next;
}
previous.Next = newLink;
newLink.Next = current;
}
}
It says that the current referenc is null while (data > current.DData && current != null), but I assigned it: current = first;
The rest is the complete code of the Program!
class Link
{
double dData;
Link next=null;
public Link Next
{
get { return next; }
set { next = value; }
}
public double DData
{
get { return dData; }
set { dData = value; }
}
public Link(double dData)
{
this.dData = dData;
}
public void DisplayLink()
{
Console.WriteLine("Link : "+ dData);
}
}
class SortedList
{
Link first;
public SortedList()
{
first = null;
}
public bool IsEmpty()
{
return (this.first == null);
}
public void Insert(double data)
{
Link newLink = new Link(data);
Link current = first;
Link previous = null;
if (first == null)
{
first = newLink;
}
else
{
while (data > current.DData && current != null)
{
previous = current;
current = current.Next;
}
previous.Next = newLink;
newLink.Next = current;
}
}
public Link Remove()
{
Link temp = first;
first = first.Next;
return temp;
}
public void DisplayList()
{
Link current;
current = first;
Console.WriteLine("Display the List!");
while (current != null)
{
current.DisplayLink();
current = current.Next;
}
}
}
class SortedListApp
{
public void TestSortedList()
{
SortedList newList = new SortedList();
newList.Insert(20);
newList.Insert(22);
newList.Insert(100);
newList.Insert(1000);
newList.Insert(15);
newList.Insert(11);
newList.DisplayList();
newList.Remove();
newList.DisplayList();
}
}
You are perhaps assuming that the while loop is breaking on the first iteration which it's not it's the assignment in the while loop that eventually breaks it.
Eventually current is NULL based on your code, you even test for it - change it to this and it should be fine:
while (current != null && data > current.DData)
{
previous = current;
current = current.Next;
}
Agree that you have done
current = first;
but then the beginning of your class first is null
class SortedList
{
Link first;
please assign something to first else it will be null

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

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.

Categories