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