using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LD_24.Code
{
///
/// Generic linked list class. Used for storing a list of values.
///
/// Target type
public class LinkedList : IEnumerable, IComparable>, IEquatable>
where T : IComparable, IEquatable
{
class Node
{
public T Data { get; set; }
public Node Next { get; set; }
public Node(T data, Node next = null)
{
Data = data;
Next = next;
}
}
private Node head;
private Node tail;
///
/// Creates an empty linked list
///
public LinkedList()
{
}
///
/// Creates an clone of a given enumerable value/list
///
/// Cloned enumerable
public LinkedList(IEnumerable other)
{
foreach (var value in other)
{
Add(value);
}
}
///
/// Add a single element to the linked list
///
///
public void Add(T value)
{
Node node = new Node(value);
if (tail != null && head != null)
{
tail.Next = node;
tail = node;
}
else
{
tail = node;
head = node;
}
}
///
/// Removes the last element from this list
///
/// The last elements values or the default value if empty
public T RemoveLast()
{
if (head == null)
{
return default;
}
Node prev = null;
Node current = head;
while (current.Next != null)
{
prev = current;
current = current.Next;
}
if (prev != null)
{
prev.Next = null;
tail = prev;
}
if (prev == null)
{
head = null;
tail = null;
}
return current.Data;
}
///
/// Gets the first element
///
/// The first element
public T GetFirst()
{
return head != null ? head.Data : default;
}
///
/// Gets the first element
///
/// The first element
public T GetLast()
{
return tail != null ? tail.Data : default;
}
///
/// Count how many elemnts are stored in this list
///
/// Number of stored elements
public int Count()
{
int count = 0;
for (Node d = head; d != null; d = d.Next)
{
count++;
}
return count;
}
///
/// Returns true if the linked list is empty,
/// what did you expect?
///
/// A boolean
public bool IsEmpty()
{
return head == null;
}
///
/// Sorts this linked list
///
public void Sort()
{
for (Node nodeA = head; nodeA != null; nodeA = nodeA.Next)
{
Node min = nodeA;
for (Node nodeB = nodeA.Next; nodeB != null; nodeB = nodeB.Next)
{
if (nodeB.Data.CompareTo(min.Data) > 0)
{
min = nodeB;
}
}
T tmp = nodeA.Data;
nodeA.Data = min.Data;
min.Data = tmp;
}
}
///
/// A human-readable string for debuging purposes
///
/// Debug string
public override string ToString()
{
return string.Format("LinkedList<{0}>( Count = {0} )", Count());
}
///
/// Enumerate over all the elements of the list
///
/// An enumerator
public IEnumerator GetEnumerator()
{
for (Node d = head; d != null; d = d.Next)
yield return d.Data;
}
///
/// Enumerate over all the elements of the list
///
/// An enumerator
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
///
/// Compares the ordering 2 lists
///
/// Other list
///
public int CompareTo(LinkedList other)
{
var otherEnumerator = other.GetEnumerator();
foreach (var value in this)
{
if (otherEnumerator.MoveNext())
{
int comparison = value.CompareTo(otherEnumerator.Current);
if (comparison != 0)
{
return comparison;
}
} else
{
return -1;
}
}
if (otherEnumerator.MoveNext())
{
return 1;
}
return 0;
}
///
/// Checks if 2 linked lists have the same values stored
///
/// Other linked list
/// True if they both store the same values
public bool Equals(LinkedList other)
{
var otherEnumerator = other.GetEnumerator();
foreach (var value in this)
{
if (otherEnumerator.MoveNext())
{
if (!value.Equals(otherEnumerator.Current))
{
// This is the case, when some elements in between the lists are different
return false;
}
}
else
{
// This is the case when the other linked list runs out of values, while this still has more.
return false;
}
}
if (otherEnumerator.MoveNext())
{
// This is the case, when the other linked list still had some left over values.
// That means it had more elements that this one.
return false;
}
// This is the case, when everything is the same.
return true;
}
}
}