How do linked list work? - c#

I am reading a tutorial and I looked all over google as well but I can't find a good explaantion of details on how a linked list works...I am really confused about the structure/Format and I really wish linked list made sense to me as they sound great, being an array thats resizeable and modifiable...Below is some code I have from a tut if you need to see what I am talking about. I am confused about the methods such as append method or delete, what they do and how tail head thingy in list work...The book just starts with an example and doesn't give explanation..
Please help with this confusion..
class ListEntry
{
int data;
ListEntry next;
public ListEntry( int d )
{
data = d;
next = null;
}
public int Data
{
get{ return data; }
set{ data = value; }
}
public ListEntry Next
{
get{ return next; }
set{ next = value; }
}
public override string ToString( )
{
return( data.ToString( ) );
}
}
class TestProgram
{
static void Main( )
{
List list = new List( );
list.Append( 3);
Console.WriteLine( list );
list.Append( 1 );
Console.WriteLine( list );
list.Append( 6 );
Console.WriteLine( list );
list.Prepend( 4 );
Console.WriteLine( list );
// continued…
// Continued…
list.Prepend( 5 );
Console.WriteLine( list );
list.DeleteFirst( 4 );
Console.WriteLine( list );
list.Prepend( 2 );
Console.WriteLine( list );
Console.WriteLine( "Head data = " + list.Head );
Console.WriteLine( "Tail data = " + list.Tail );
list.Clear( );
Console.WriteLine( list );
Console.WriteLine( "IsEmpty = " + list.IsEmpty );
}
}
using System;
class List
{
ListEntry head;
ListEntry tail;
class ListEntry
{
// Put declaration of ListEntry here. Nesting of the classes is valid. In fact, class nesting is
// preferable if one class is only used within the context of another class.
}
public List( )
{
head = null;
tail = null;
}
// Continued…
public int Head
{
get{ return head.Data; }
}
public int Tail
{
get{ return tail.Data; }
}
public bool IsEmpty
{
get{ return( head == null ); }
}
public override string ToString( )
{
string tmp = "";
ListEntry current = head;
if( current == null )
{
tmp = "Empty";
}
while( current != null )
{
tmp += current + " ";
current = current.Next;
}
return( tmp );
}
public void Append( int i )
{
ListEntry tmp = new ListEntry( i );
tmp.Next = null;
if( head == null )
{
head = tmp;
}
else
{
tail.Next = tmp;
}
tail = tmp;
}
public void Prepend( int i )
{
ListEntry tmp = new ListEntry( i );
tmp.Next = head;
if( head == null )
{
tail = tmp;
}
head = tmp;
}
public void DeleteFirst( int i )
{
ListEntry current = head;
ListEntry previous = null;
while( current != null && current.Data != i )
{
previous = current;
current = current.Next;
}
if( current == null )
{
throw new ArgumentException( "List entry not found" );
}
// Continued…
// Continued…
if( current == head )
{
head = current.Next;
}
else
{
previous.Next = current.Next;
}
if( current == tail )
{
tail = previous;
}
}
There are other methods such as :
A Sort( ) method
A FindFirst( ) method
A FindNext( ) method
An InsertBefore( ) method
An InsertAfter( ) method
But for now the basic ones are fine..

A Linked List is a data structured used for collecting a sequence of objects. The "Head" is the very first item in the sequence. The "Tail" is the last object in the sequence. Each item in the linked list (a node) will have a property called Next (and Previous if it is doubly linked) which points to the Next or Previous item in the list. These next and previous items just point to the next or previous item in the collection, so to iterate over them you have to do it in order.
Think of a linked list like links in a chain. To get to the 5th item in the list, you start at the very first link in the chain and then follow it until you get to the 5th item. Hope this helps a little.
http://en.wikipedia.org/wiki/Linked_list

A simple singly-linked list implementation in C# (generic):
public class LinkedList<T>
{
private Node<T> head;
public void AddAtFront(T data)
{
this.head = new Node<T>(data, this.head);
}
public void AddAtBack(T data)
{
var node = new Node<T>(data);
var current = this.head;
if (current == null)
{
this.head = node;
}
else
{
while (current.Next != null)
{
current = current.Next;
}
current.Next = node;
}
}
public Node<T> Front
{
get
{
return this.head;
}
}
public Node<T> Back
{
get
{
var current = this.head;
if (current != null)
{
while (current.Next != null)
{
current = current.Next;
}
}
return current;
}
}
public Node<T> RemoveAtFront()
{
var node = this.head;
if (node != null)
{
this.head = node.Next;
}
return node;
}
public Node<T> RemoveAtBack()
{
var current = this.head;
if (current != null)
{
if (current.Next == null)
{
this.head = null;
}
else
{
Node<T> nextToLast = null;
while (current.Next != null)
{
nextToLast = current;
current = current.Next;
}
nextToLast.Next = null;
}
}
return current;
}
}
and
public class Node<T>
{
private readonly T data;
private Node<T> next;
public Node(T data)
{
this.data = data;
}
public Node(T data, Node<T> next)
{
this.data = data;
this.next = next;
}
public T Data
{
get
{
return this.data;
}
}
public Node<T> Next
{
get
{
return this.next;
}
set
{
this.next = value;
}
}
}

Related

How to modify my CustLinkedList to implement insert more efficiently

I created a custom linked list on a whiteboard, for learning purposes.
CustDoublyLinkedList class with the nested Node class, but when it is time to insert, at the specified index method must loop through until it get to an index to insert. I want to insert directly without using loop as my Add or PushFront methods work.
I also added some more method like IndexOf and Contain methods for the list
CustDoublyLinkedList<int> myList = new();
myList.Add(12);
myList.Add(13);
myList.Add(14);
myList.Add(45);
myList.Add(28);
myList.Add(120);
myList.PushFront(32);
myList.Insert(3,1500);
for (int i = 0; i < myList.Count; i++)
{
Console.WriteLine(myList[i]);
}
class CustDoublyLinkedList<T>
{
private class Node
{
public T Element { get; set; }
public Node NextNode { get; set; }
public Node PrevNode { get; set; }
public Node(T data)
{
this.Element = data;
this.PrevNode = null;
this.NextNode = null;
}
public Node(T data, Node prevNode): this(data)
{
prevNode.NextNode = this;
}
public Node(T data, Node prevNode, Node nextNode) : this(data, prevNode)
{
nextNode.PrevNode = this;
}
}
private Node head;
private Node tail;
private int counter;
public CustDoublyLinkedList()
{
this.head = null;
this.tail = null;
this.counter = 0;
}
public void Insert(int index, T item)
{
if (index == 0)
{
throw new ArgumentOutOfRangeException("You Can Push with PushFront Method at Index: " + index);
}
if (index < 0 || index >= this.counter)
{
throw new ArgumentOutOfRangeException("invalid Index: " + index);
}
Node newNode = new(item);
Node currentNode = this.head;
for (int i = 0; i < index - 1; i++)
{
currentNode = currentNode.NextNode;
}
newNode.NextNode = currentNode.NextNode;
newNode.PrevNode = currentNode.PrevNode;
currentNode.NextNode = newNode;
this.counter++;
}
public void Add(T item)
{
if (this.head == null)
{
this.head = new(item);
this.tail = this.head;
}
else
{
Node newNode = new(item, this.tail);
this.tail = newNode;
}
this.counter++;
}
public void PushFront(T item)
{
Node newNode = new(item);
newNode.NextNode = this.head;
newNode.PrevNode = null;
if(this.head != null)
{
this.head.PrevNode = newNode;
}
this.head = newNode;
this.counter++;
}
public bool Contain(T item)
{
int index = IndexOf(item);
if (index != -1)
{
return true;
}
return false;
}
public int IndexOf(T item)
{
Node currentNode = this.head;
int index = 0;
while(currentNode != null)
{
if (object.Equals(currentNode.Element, item))
{
return index;
}
currentNode = currentNode.NextNode;
index++;
}
return -1;
}
public int Count
{
get { return this.counter; }
}
public T this[int index]
{
get
{
if (index < 0 || index >= this.counter)
{
throw new IndexOutOfRangeException("Invalid Index: " + index);
}
Node currentNode = this.head;
for (int i = 0; i < index; i++)
{
currentNode = currentNode.NextNode;
}
return currentNode.Element;
}
set
{
if (index < 0 || index >= this.counter)
{
throw new IndexOutOfRangeException("Invalid Index: " + index);
}
Node currentNode = this.head;
for (int i = 0; i < index; i++)
{
currentNode = currentNode.NextNode;
}
currentNode.Element = value;
}
}
}
You are looking for a Skip List
With this you can drive your insert requirement to O(log N) on average while still maintaining a linked list structure

Endless loop IntNode

before showing the issue, look at the IntNode class:
class IntNode
{
public int value { get; set; }
public IntNode next { get; set; }
public IntNode(int value)
{
this.value = value;
this.next = null;
}
public IntNode(int value, IntNode next)
{
this.value = value;
this.next = next;
}
public bool HasNext ()
{
return (this.next != null);
}
public override string ToString()
{
if (this.HasNext())
return this.value + " --> " + this.next;
else
return this.value + ". [end]";
}
}
I have the following function:
static IntNode Sort (IntNode head)
{
IntNode pos = head.next;
IntNode current = head;
IntNode prev = head;
bool changed = false;
while (current != null)
{
while (pos != null)
{
if (current.value > pos.value)
{
if (pos.HasNext()) current.next = pos.next;
else prev.next = pos;
pos.next = current;
changed = true;
if (current.next.HasNext())
pos = current.next.next;
break;
}
pos = pos.next;
}
if (!changed)
{
current.next = head;
head = current;
}
prev = current;
current = current.next;
changed = false;
}
return head;
}
But when I am launching the program (with given parameters) it is not responding (a "-" appears and disappears) I dont know why it is like that and I am sitting on this a hour...
The purpose of the program is to a list and sort it from smaller to bigger and than return the edited list (dont create another list).
For Example:
Given list:
6,-4,5,0
Output:
-4,0,5,6
Thanks!
I can see several issues with how your bubble sort is written. If you don't have a debugger it will be difficult to debug manually. Here is an insertion sort that may do the trick for you and be easier to trace mentally. It finds the lowest value and moves it to a different list.
static IntNode Sort (IntNode head)
{
IntNode resultTail = null;
IntNode resultHead = null;
IntNode current = head;
IntNode lowestPrev = null;
IntNode lowest = head;
while (head != null)
{
lowestPrev = null;
current = head;
while (current != null)
{
if (current.value < lowest.value)
{
lowest = current;
lowestPrev = prev;
}
prev = current
current = current.next;
}
if (resultHead = null)
{
resultHead = lowest;
resultTail = lowest;
}
else
resultTail.next = lowest;
if (lowest == head)
head = head.next;
else
lowestPrev.next = lowest.next;
}
return resultHead;
}

Storing multiple Linked Lists in an Array List. How to best access them and perform a linked list specific operation on them?

I am storing Linked Lists in an Array List. Each linked list contains different items. I would like to retrieve a particular linkedlist from the array list such as at index position 0 of the and perform certain operations e.g. traversing from the front. However I am having problems getting the array items to be recognised as linked lists. What would be the best way of doing that?
E.g if I have
static ArrayList ar = new ArrayList();
static DLinkedList b = new DLinkedList();
And would like to do the following.
b.TraverseFront(ar[0]);
I have given an example below which I implemented in C#
class Program
{
static ArrayList ar = new ArrayList();
static DLinkedList b = new DLinkedList();
static void Main(string[] args)
{
store("huggo boss");
b.TraverseFront(ar[0]); // THIS IS WHAT I'D LIKE TO DO BUT I DON'T KNOW HOW TO DO IT
}
private static void store(string s)
{
DLinkedList linkedListNode = new DLinkedList();
string output = null;
string norm = null;
int token = 3;
for (int i = 0; i < s.Length; i++)
{
if (!String.IsNullOrWhiteSpace(char.ToString(s[i])))
{
output = output + s[i];
}
}
for (int j = 0; j < output.Length - token + 1 ; j++)
{
norm = norm + output[j] + output[j + 1] + output[j + 2]
linkedListNode.InsertNext(norm);
norm = null;
}
}
}
}
class DLinkedList
{
private Object data;
private DLinkedList next;
private DLinkedList prev;
/*
static void Main(string[] args)
{
DLinkedList node1 = new DLinkedList(1);
DLinkedList node3 = node1.InsertNext(3);
DLinkedList node2 = node3.InsertPrev(2);
DLinkedList node5 = node3.InsertNext(5);
DLinkedList node4 = node5.InsertPrev(4);
node1.TraverseFront();
node5.TraverseBack();
Console.Read();
}
*/
public DLinkedList()
{
data = null;
next = null;
prev = null;
}
public DLinkedList(Object value)
{
data = value;
next = null;
prev = null;
}
public DLinkedList InsertNext(Object value)
{
DLinkedList node = new DLinkedList(value);
if (this.next == null)
{
// Easy to handle
node.prev = this;
node.next = null; // already set in constructor
this.next = node;
}
else
{
// Insert in the middle
DLinkedList temp = this.next;
node.prev = this;
node.next = temp;
this.next = node;
temp.prev = node;
// temp.next does not have to be changed
}
return node;
}
public DLinkedList InsertPrev(Object value)
{
DLinkedList node = new DLinkedList(value);
if (this.prev == null)
{
node.prev = null; // already set on constructor
node.next = this;
this.prev = node;
}
else
{
// Insert in the middle
DLinkedList temp = this.prev;
node.prev = temp;
node.next = this;
this.prev = node;
temp.next = node;
// temp.prev does not have to be changed
}
return node;
}
public void TraverseFront()
{
TraverseFront(this);
}
public void TraverseFront(DLinkedList node)
{
if (node == null)
node = this;
System.Console.WriteLine("\n\nTraversing in Forward
Direction\n\n");
while (node != null)
{
System.Console.WriteLine(node.data);
node = node.next;
}
}
public void TraverseBack()
{
TraverseBack(this);
}
public void TraverseBack(DLinkedList node)
{
if (node == null)
node = this;
while (node != null)
{
System.Console.WriteLine(node.data);
node = node.prev;
}
}
internal void TraverseFront(object p)
{
throw new NotImplementedException();
}
}
}

Doubly LinkedList traversing

I have write a C# code to insert data to a doubly linked list and to delete a node. It is working and I can traverse the list from last node to first. But I can not traverse the list from first node to the last. I can not find the mistake I have made. Following is my code.
class Node
{
public string data { get; set; }
public Node next { get; set; }
public Node previous { get; set; }
public Node(string data)//first node)
{
this.data = data;
this.next = null;
this.previous = null;
}
public Node(string data, Node next,Node previous)
{
this.data = data;
this.next = next;
this.previous = previous;
}
}
class doublyLinkedList
{
private Node first;
private Node last;
private int size;
public doublyLinkedList()
{
this.first = null;
this.last = null;
this.size = 0;
}
public bool isEmpty
{
get { return this.size == 0; }
}
public int count
{
get { return this.size; }
}
public void Add(string o)
{
Node current = this.last;
if (this.isEmpty)
{
this.first = new Node(o);
this.last = new Node(o);
}
else
{
current.next = new Node(o, current.next,current);
last = current.next;
Console.WriteLine("first " + first.data + "last " + last.data + "previous " + last.previous.data);
}size++;
}
public object getFirst()
{
return first.data;
}
public string remove()
{
Node current = this.last;
current.previous.next = null;
object removedElement = current.data;
string reEle = ((String)(removedElement).ToString());
current = current.previous;
size--;
return reEle;
}
public void TraverseFront()
{
Node current = this.first;
string str = current.data;
Console.WriteLine("first " + str);
Node current1 = first.next;
string str1 = first.next.data;
string question = str + str1;
Console.WriteLine(question)
}
}
Your problem is when you insert the first object. You need to set last to the same instance as first, as at the moment you are disconnecting the first object (this.first.next is always null), change it from:
this.last = new Node(o);
to:
this.last = this.first;

How to solve Josephus Elimination using Circular linked list

class Node
{
public int Data { get; set; }
public Node Next { get; set; }
public int Counter { get; set; }
public Node(int element,int counter)
{
Data = element;
Counter = counter;
Next=null;
}
}
I use counter as a TAG on person, or in other words the position from which elimination starts.
class CircularLinkedList
{
Node first;
Node last;
public CircularLinkedList()
{
first = last = null;
}
protected void Insert(int element,int counter)
{
if (IsEmpty())
{
first = last = new Node(element,counter);
}
else
{
last.Next = last = new Node(element,counter);
last.Next = first;
}
}
public int RemoveAt(int index)
{
int value = 0;
Node current = first;
do
{
if (current.Counter == index)
{
value = current.Data;
}
current = current.Next;
} while (current != first);
return value;
}
public void AddMen(int n)
{
for (int i = 1; i <= n; i++)
{
Insert(i*2,i);
}
}
public int Eliminate(int m)
{
int value = 0;
Node current = first;
do
{
value = RemoveAt(m);
current = current.Next;
} while (current != first);
return value;
}
public bool IsEmpty()
{
return first == null;
}
public void Display()
{
Node current = first;
do
{
Console.WriteLine(current.Counter+" "+current.Data+" ");
current = current.Next;
} while (current!=first);
}
}
I am having problem with elimination method, I want it must be constantly called until the list is empty,
I would do:
public int Eliminate(int m)
{
int value = 0;
Node current = first;
Node nextNode;
do
{
nextNode = current.next;
value = RemoveAt(m);
current = nextNode;
} while (current != first);
return value;
}

Categories