From b313b08bc78aad6fac053143206ca9e9baf7d0a9 Mon Sep 17 00:00:00 2001 From: mavantgarderc Date: Fri, 5 Dec 2025 21:54:08 +0330 Subject: [PATCH 1/2] DataStructure(LinkedList): Singly, Doubly, Circular, DoublyCircular --- .../CircularDoublyLinkedFirst.AddFirst.cs | 33 +++ .../CircularDoublyLinkedList.AddLast.cs | 29 +++ .../CircularDoublyLinkedList.AddRange.cs | 19 ++ .../CircularDoublyLinkedList.Clear.cs | 15 ++ .../CircularDoublyLinkedList.Clone.cs | 29 +++ .../CircularDoublyLinkedList.Contains.cs | 34 +++ .../CircularDoublyLinkedList.Count.cs | 13 ++ .../CircularDoublyLinkedList.Enumeration.cs | 41 ++++ .../CircularDoublyLinkedList.GetNodeDepth.cs | 37 +++ ...cularDoublyLinkedList.GetStructuralInfo.cs | 31 +++ .../CircularDoublyLinkedList.HasCycle.cs | 14 ++ .../CircularDoublyLinkedList.PeekFirst.cs | 20 ++ .../CircularDoublyLinkedList.PeekLast.cs | 21 ++ .../CircularDoublyLinkedList.Remove.cs | 50 +++++ .../CircularDoublyLinkedList.RemoveFirst.cs | 35 +++ .../CircularDoublyLinkedList.RemoveLast.cs | 32 +++ .../CircularDoublyLinkedList.Reverse.cs | 30 +++ ...ircularDoublyLinkedList.ReverseIterator.cs | 27 +++ .../CircularDoublyLinkedList.ToArray.cs | 28 +++ .../LinkedLists/CircularDoublyLinkedList.cs | 28 +++ .../CircularLinkedList.AddFirst.cs | 27 +++ .../LinkedLists/CircularLinkedList.AddLast.cs | 18 ++ .../CircularLinkedList.AddRange.cs | 19 ++ .../LinkedLists/CircularLinkedList.Clear.cs | 15 ++ .../LinkedLists/CircularLinkedList.Clone.cs | 30 +++ .../CircularLinkedList.Contains.cs | 35 +++ .../LinkedLists/CircularLinkedList.Count.cs | 13 ++ .../CircularLinkedList.Enumeration.cs | 39 ++++ .../CircularLinkedList.GetNodeDepth.cs | 36 +++ .../CircularLinkedList.GetStructuralInfo.cs | 30 +++ .../CircularLinkedList.HasCycle.cs | 14 ++ .../CircularLinkedList.PeekFirst.cs | 19 ++ .../CircularLinkedList.PeekLast.cs | 18 ++ .../LinkedLists/CircularLinkedList.Remove.cs | 49 ++++ .../CircularLinkedList.RemoveFirst.cs | 29 +++ .../CircularLinkedList.RemoveLast.cs | 36 +++ .../LinkedLists/CircularLinkedList.Reverse.cs | 32 +++ .../CircularLinkedList.ReverseIterator.cs | 33 +++ .../LinkedLists/CircularLinkedList.ToArray.cs | 28 +++ .../LinkedLists/CircularLinkedList.cs | 26 +++ .../LinkedLists/DoublyLinkedList.AddFirst.cs | 28 +++ .../LinkedLists/DoublyLinkedList.AddLast.cs | 28 +++ .../LinkedLists/DoublyLinkedList.AddRange.cs | 19 ++ .../LinkedLists/DoublyLinkedList.Clear.cs | 16 ++ .../LinkedLists/DoublyLinkedList.Clone.cs | 22 ++ .../LinkedLists/DoublyLinkedList.Contains.cs | 13 ++ .../LinkedLists/DoublyLinkedList.Count.cs | 13 ++ .../DoublyLinkedList.Enumeration.cs | 20 ++ .../LinkedLists/DoublyLinkedList.Find.cs | 25 +++ .../DoublyLinkedList.GetNodeDepth.cs | 30 +++ .../DoublyLinkedList.GetStructuralInfo.cs | 30 +++ .../LinkedLists/DoublyLinkedList.HasCycle.cs | 32 +++ .../LinkedLists/DoublyLinkedList.PeekFirst.cs | 18 ++ .../LinkedLists/DoublyLinkedList.PeekLast.cs | 18 ++ .../LinkedLists/DoublyLinkedList.Remove.cs | 36 +++ .../DoublyLinkedList.RemoveFirst.cs | 30 +++ .../DoublyLinkedList.RemoveLast.cs | 30 +++ .../LinkedLists/DoublyLinkedList.Reverse.cs | 34 +++ .../DoublyLinkedList.ReverseIterator.cs | 20 ++ .../LinkedLists/DoublyLinkedList.ToArray.cs | 22 ++ .../LinkedLists/DoublyLinkedList.cs | 13 ++ .../LinkedLists/DoublyLinkedListEnumerator.cs | 84 +++++++ .../DataStructures/LinkedLists/ILinkedList.cs | 160 +++++++++++++ .../LinkedListExtensions.AsReadOnly.cs | 60 +++++ .../LinkedListExtensions.DebugPrint.cs | 36 +++ .../LinkedListExtensions.Filter.cs | 43 ++++ .../LinkedListExtensions.ForEach.cs | 36 +++ .../LinkedLists/LinkedListExtensions.Map.cs | 41 ++++ .../LinkedListExtensions.Partition.cs | 52 +++++ .../LinkedListExtensions.Reduce.cs | 46 ++++ .../LinkedListExtensions.Synchronized.cs | 212 ++++++++++++++++++ .../LinkedLists/LinkedListExtensions.cs | 12 + .../LinkedLists/LinkedListNode.cs | 33 +++ .../LinkedLists/SinglyLinkedLisst.Contains.cs | 26 +++ .../LinkedLists/SinglyLinkedList.AddFirst.cs | 27 +++ .../LinkedLists/SinglyLinkedList.AddLast.cs | 27 +++ .../LinkedLists/SinglyLinkedList.AddRange.cs | 22 ++ .../LinkedLists/SinglyLinkedList.Clear.cs | 16 ++ .../LinkedLists/SinglyLinkedList.Clone.cs | 22 ++ .../LinkedLists/SinglyLinkedList.Count.cs | 13 ++ .../SinglyLinkedList.Enumeration.cs | 20 ++ .../SinglyLinkedList.GetStructuralInfo.cs | 30 +++ .../LinkedLists/SinglyLinkedList.HasCycle.cs | 32 +++ .../LinkedLists/SinglyLinkedList.PeekFirst.cs | 18 ++ .../LinkedLists/SinglyLinkedList.PeekLast.cs | 18 ++ .../LinkedLists/SinglyLinkedList.Remove.cs | 48 ++++ .../SinglyLinkedList.RemoveFirst.cs | 26 +++ .../SinglyLinkedList.RemoveLast.cs | 37 +++ .../LinkedLists/SinglyLinkedList.Reverse.cs | 31 +++ .../SinglyLinkedList.ReverseIterator.cs | 26 +++ .../LinkedLists/SinglyLinkedList.ToArray.cs | 22 ++ .../LinkedLists/SinglyLinkedList.cs | 13 ++ .../LinkedLists/SinglyLinkedListEnumerator.cs | 84 +++++++ .../LinkedLists/SinglyLinkedListNode.cs | 28 +++ .../SinglyLinkedLists.GetNodeDepth.cs | 31 +++ 95 files changed, 3041 insertions(+) create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedFirst.AddFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.AddLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.AddRange.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Clear.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Clone.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Contains.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Count.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Enumeration.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.GetNodeDepth.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.GetStructuralInfo.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.HasCycle.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.PeekFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.PeekLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Remove.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.RemoveFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.RemoveLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Reverse.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.ReverseIterator.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.ToArray.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddRange.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Clear.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Clone.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Contains.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Count.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Enumeration.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.GetNodeDepth.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.GetStructuralInfo.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.HasCycle.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.PeekFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.PeekLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Remove.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.RemoveFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.RemoveLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Reverse.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.ReverseIterator.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.ToArray.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddRange.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Clear.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Clone.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Contains.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Count.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Enumeration.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Find.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.GetNodeDepth.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.GetStructuralInfo.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.HasCycle.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.PeekFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.PeekLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Remove.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.RemoveFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.RemoveLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Reverse.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.ReverseIterator.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.ToArray.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/DoublyLinkedListEnumerator.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/ILinkedList.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.AsReadOnly.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.DebugPrint.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Filter.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.ForEach.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Map.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Partition.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Reduce.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Synchronized.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/LinkedListNode.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedLisst.Contains.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddRange.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Clear.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Clone.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Count.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Enumeration.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.GetStructuralInfo.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.HasCycle.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.PeekFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.PeekLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Remove.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.RemoveFirst.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.RemoveLast.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Reverse.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.ReverseIterator.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.ToArray.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedListEnumerator.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedListNode.cs create mode 100644 src/Csdsa/DataStructures/LinkedLists/SinglyLinkedLists.GetNodeDepth.cs diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedFirst.AddFirst.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedFirst.AddFirst.cs new file mode 100644 index 0000000..36f1c0f --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedFirst.AddFirst.cs @@ -0,0 +1,33 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public void AddFirst(T item) + { + LinkedListNode newNode = new LinkedListNode(item); + + if (_head == null) + { + newNode.Next = newNode; + newNode.Prev = newNode; + _head = newNode; + } + else + { + LinkedListNode tail = Tail; + + newNode.Next = _head; + newNode.Prev = tail; + tail.Next = newNode; + _head.Prev = newNode; + _head = newNode; + } + + _count++; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.AddLast.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.AddLast.cs new file mode 100644 index 0000000..6608a4a --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.AddLast.cs @@ -0,0 +1,29 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public void AddLast(T item) + { + if (_head == null) + { + AddFirst(item); + } + else + { + LinkedListNode newNode = new LinkedListNode(item); + LinkedListNode tail = Tail; + + newNode.Next = _head; + newNode.Prev = tail; + tail.Next = newNode; + _head.Prev = newNode; + } + + _count++; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.AddRange.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.AddRange.cs new file mode 100644 index 0000000..46a9841 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.AddRange.cs @@ -0,0 +1,19 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method +/// for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public void AddRange(IEnumerable items) + { + ArgumentNullException.ThrowIfNull(items); + + foreach (T item in items) + { + AddLast(item); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Clear.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Clear.cs new file mode 100644 index 0000000..c08f72c --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Clear.cs @@ -0,0 +1,15 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public void Clear() + { + _head = null; + _count = 0; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Clone.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Clone.cs new file mode 100644 index 0000000..8a73b44 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Clone.cs @@ -0,0 +1,29 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public ILinkedList Clone() + { + CircularDoublyLinkedList clone = new CircularDoublyLinkedList(); + + if (_head == null) + { + return clone; + } + + LinkedListNode current = _head; + + do + { + clone.AddLast(current.Value); + current = current.Next; + } + while (!ReferenceEquals(current, _head)); + + return clone; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Contains.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Contains.cs new file mode 100644 index 0000000..7c53b96 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Contains.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public bool Contains(T item) + { + if (_head == null) + { + return false; + } + + LinkedListNode current = _head; + EqualityComparer comparer = EqualityComparer.Default; + + do + { + if (comparer.Equals(current.Value, item)) + { + return true; + } + + current = current.Next; + } + while (!ReferenceEquals(current, _head)); + + return false; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Count.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Count.cs new file mode 100644 index 0000000..ae100e7 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Count.cs @@ -0,0 +1,13 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the property for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public int Count + { + get { return _count; } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Enumeration.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Enumeration.cs new file mode 100644 index 0000000..7af724c --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Enumeration.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides enumeration for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public IEnumerator GetEnumerator() + { + if (_head == null) + { + yield break; + } + + LinkedListNode start = _head; + LinkedListNode current = start; + int version = _version; + + do + { + if (version != _version) + { + throw new InvalidOperationException("Collection modified"); + } + + yield return current.Value; + current = current.Next; + } + while (!ReferenceEquals(current, start)); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.GetNodeDepth.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.GetNodeDepth.cs new file mode 100644 index 0000000..8ba705e --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.GetNodeDepth.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the implementation +/// for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public int GetNodeDepth(T item) + { + if (_head == null) + { + return -1; + } + + int depth = 0; + LinkedListNode current = _head; + EqualityComparer comparer = EqualityComparer.Default; + + do + { + if (comparer.Equals(current.Value, item)) + { + return depth; + } + + depth++; + current = current.Next; + } + while (!ReferenceEquals(current, _head)); + + return -1; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.GetStructuralInfo.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.GetStructuralInfo.cs new file mode 100644 index 0000000..1fc4b1a --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.GetStructuralInfo.cs @@ -0,0 +1,31 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the implementation +/// for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public (int Length, int MidIndex) GetStructuralInfo() + { + if (_head == null) + { + return (0, -1); + } + + LinkedListNode slow = _head; + LinkedListNode fast = _head; + int index = 0; + + do + { + slow = slow.Next; + fast = fast.Next.Next; + index++; + } + while (!ReferenceEquals(fast, _head) && !ReferenceEquals(fast.Next, _head)); + + return (_count, index); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.HasCycle.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.HasCycle.cs new file mode 100644 index 0000000..09d2c48 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.HasCycle.cs @@ -0,0 +1,14 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public bool HasCycle() + { + // By design, this implementation always represents a circular list. + return true; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.PeekFirst.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.PeekFirst.cs new file mode 100644 index 0000000..e02aac8 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.PeekFirst.cs @@ -0,0 +1,20 @@ +using System; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public T PeekFirst() + { + if (_head == null) + { + throw new InvalidOperationException("list is empty"); + } + + return _head.Value; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.PeekLast.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.PeekLast.cs new file mode 100644 index 0000000..3805d47 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.PeekLast.cs @@ -0,0 +1,21 @@ +using System; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public T PeekLast() + { + if (_head == null) + { + throw new InvalidOperationException("List is empty"); + } + + LinkedListNode tail = Tail; + return tail.Value; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Remove.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Remove.cs new file mode 100644 index 0000000..ae70652 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Remove.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public bool Remove(T item) + { + if (_head == null) + { + return false; + } + + EqualityComparer comparer = EqualityComparer.Default; + LinkedListNode current = _head; + + do + { + if (comparer.Equals(current.Value, item)) + { + if (ReferenceEquals(current, _head)) + { + RemoveFirst(); + } + else if (ReferenceEquals(current, Tail)) + { + RemoveLast(); + } + else + { + current.Prev.Next = current.Next; + current.Next.Prev = current.Prev; + _count--; + _version++; + } + + return true; + } + + current = current.Next; + } + while (!ReferenceEquals(current, _head)); + + return false; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.RemoveFirst.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.RemoveFirst.cs new file mode 100644 index 0000000..27ef5a5 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.RemoveFirst.cs @@ -0,0 +1,35 @@ +using System; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public void RemoveFirst() + { + if (_head == null) + { + throw new InvalidOperationException("bro list is empty..."); + } + + if (_head.Next == _head) + { + _head = null; + } + else + { + LinkedListNode newHead = _head.Next; + LinkedListNode tail = Tail; + + newHead.Prev = tail; + tail.Next = newHead; + _head = newHead; + } + + _count--; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.RemoveLast.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.RemoveLast.cs new file mode 100644 index 0000000..e515e92 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.RemoveLast.cs @@ -0,0 +1,32 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public void RemoveLast() + { + if (_head == null) + { + throw new InvalidOperationException("list is empty bro..."); + } + + if (_head.Next == _head) + { + _head = null; + } + else + { + LinkedListNode tail = Tail; + LinkedListNode newTail = tail.Prev; + + newTail.Next = _head; + _head.Prev = newTail; + } + + _count--; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Reverse.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Reverse.cs new file mode 100644 index 0000000..da2f80e --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.Reverse.cs @@ -0,0 +1,30 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public void Reverse() + { + if (_head == null || _head.Next == _head) + { + return; + } + + LinkedListNode current = _head; + + do + { + LinkedListNode temp = current.Prev; + current.Prev = current.Next; + current.Next = temp; + current = current.Prev; + } + while (!ReferenceEquals(current, _head)); + + _head = _head.Next; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.ReverseIterator.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.ReverseIterator.cs new file mode 100644 index 0000000..8856b54 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.ReverseIterator.cs @@ -0,0 +1,27 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides implementation +/// for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public System.Collections.Generic.IEnumerable ReverseIterator() + { + if (_head == null) + { + yield break; + } + + LinkedListNode start = Tail; + LinkedListNode current = start; + + do + { + yield return current.Value; + current = current.Prev; + } + while (!ReferenceEquals(current, start)); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.ToArray.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.ToArray.cs new file mode 100644 index 0000000..94fdcb5 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.ToArray.cs @@ -0,0 +1,28 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularDoublyLinkedList +{ + /// + public T[] ToArray() + { + T[] array = new T[_count]; + + if (_head == null) + { + return array; + } + + LinkedListNode current = _head; + + for (int i = 0; i < _count; i++) + { + array[i] = current.Value; + current = current.Next; + } + + return array; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.cs b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.cs new file mode 100644 index 0000000..2c68c50 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularDoublyLinkedList.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Represents a circular doubly linked list implementation of . +/// The list maintains a reference to the head node; the tail is head.Prev. +/// +/// The element type. +public partial class CircularDoublyLinkedList : ILinkedList +{ + private LinkedListNode _head; + private int _count; + private int _version; + + private LinkedListNode Tail + { + get + { + if (_head == null) + { + return null; + } + + return _head.Prev; + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddFirst.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddFirst.cs new file mode 100644 index 0000000..bc6ef35 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddFirst.cs @@ -0,0 +1,27 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public void AddFirst(T item) + { + SinglyLinkedListNode newNode = new SinglyLinkedListNode(item); + + if (_tail == null) + { + _tail = newNode; + newNode.Next = newNode; + } + else + { + newNode.Next = _tail.Next; + _tail.Next = newNode; + } + + _count++; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddLast.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddLast.cs new file mode 100644 index 0000000..e57fd82 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddLast.cs @@ -0,0 +1,18 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public void AddLast(T item) + { + AddFirst(item); + + if (_tail != null) + { + _tail = _tail.Next; + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddRange.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddRange.cs new file mode 100644 index 0000000..164ad46 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.AddRange.cs @@ -0,0 +1,19 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method +/// for . +/// +public partial class CircularLinkedList +{ + /// + public void AddRange(IEnumerable items) + { + ArgumentNullException.ThrowIfNull(items); + + foreach (T item in items) + { + AddLast(item); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Clear.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Clear.cs new file mode 100644 index 0000000..492aa7d --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Clear.cs @@ -0,0 +1,15 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public void Clear() + { + _tail = null; + _count = 0; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Clone.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Clone.cs new file mode 100644 index 0000000..bf20eed --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Clone.cs @@ -0,0 +1,30 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public ILinkedList Clone() + { + CircularLinkedList clone = new CircularLinkedList(); + + if (_tail == null) + { + return clone; + } + + SinglyLinkedListNode current = Head; + SinglyLinkedListNode start = current; + + do + { + clone.AddLast(current.Value); + current = current.Next; + } + while (!ReferenceEquals(current, start)); + + return clone; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Contains.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Contains.cs new file mode 100644 index 0000000..dd60ec9 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Contains.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public bool Contains(T item) + { + if (_tail == null) + { + return false; + } + + SinglyLinkedListNode current = Head; + SinglyLinkedListNode start = current; + EqualityComparer comparer = EqualityComparer.Default; + + do + { + if (comparer.Equals(current.Value, item)) + { + return true; + } + + current = current.Next; + } + while (!ReferenceEquals(current, start)); + + return false; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Count.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Count.cs new file mode 100644 index 0000000..d73902b --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Count.cs @@ -0,0 +1,13 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the property for . +/// +public partial class CircularLinkedList +{ + /// + public int Count + { + get { return _count; } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Enumeration.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Enumeration.cs new file mode 100644 index 0000000..20c10a3 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Enumeration.cs @@ -0,0 +1,39 @@ +using System.Collections; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides enumeration for . +/// +public partial class CircularLinkedList +{ + /// + public IEnumerator GetEnumerator() + { + if (_tail == null) + { + yield break; + } + + SinglyLinkedListNode start = Head; + SinglyLinkedListNode current = start; + int version = _version; + + do + { + if (version != _version) + { + throw new InvalidOperationException("collection modified"); + } + + yield return current.Value; + current = current.Next; + } + while (!ReferenceEquals(current, start)); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.GetNodeDepth.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.GetNodeDepth.cs new file mode 100644 index 0000000..d7c7e47 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.GetNodeDepth.cs @@ -0,0 +1,36 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the implementation +/// for . +/// +public partial class CircularLinkedList +{ + /// + public int GetNodeDepth(T item) + { + if (_tail == null) + { + return -1; + } + + int depth = 0; + SinglyLinkedListNode current = Head; + SinglyLinkedListNode start = current; + EqualityComparer comparer = EqualityComparer.Default; + + do + { + if (comparer.Equals(current.Value, item)) + { + return depth; + } + + depth++; + current = current.Next; + } + while (!ReferenceEquals(current, start)); + + return -1; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.GetStructuralInfo.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.GetStructuralInfo.cs new file mode 100644 index 0000000..a432c08 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.GetStructuralInfo.cs @@ -0,0 +1,30 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the implementation +/// for . +/// +public partial class CircularLinkedList +{ + /// + public (int Length, int MidIndex) GetStructuralInfo() + { + if (_tail == null) + { + return (0, -1); + } + + SinglyLinkedListNode slow = Head; + SinglyLinkedListNode fast = Head; + int index = 0; + + for (int i = 0; i < _count / 2; i++) + { + slow = slow.Next; + fast = fast.Next.Next; + index++; + } + + return (_count, index); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.HasCycle.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.HasCycle.cs new file mode 100644 index 0000000..d4ce148 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.HasCycle.cs @@ -0,0 +1,14 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public bool HasCycle() + { + // By design, this implementation always represents a circular list. + return true; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.PeekFirst.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.PeekFirst.cs new file mode 100644 index 0000000..e0de359 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.PeekFirst.cs @@ -0,0 +1,19 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public T PeekFirst() + { + if (_tail == null) + { + throw new InvalidOperationException("List is empty"); + } + + SinglyLinkedListNode head = Head; + return head.Value; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.PeekLast.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.PeekLast.cs new file mode 100644 index 0000000..44f5754 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.PeekLast.cs @@ -0,0 +1,18 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public T PeekLast() + { + if (_tail == null) + { + throw new InvalidOperationException("List is empty"); + } + + return _tail.Value; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Remove.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Remove.cs new file mode 100644 index 0000000..76443f2 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Remove.cs @@ -0,0 +1,49 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public bool Remove(T item) + { + if (_tail == null) + { + return false; + } + + EqualityComparer comparer = EqualityComparer.Default; + SinglyLinkedListNode head = Head; + + if (comparer.Equals(head.Value, item)) + { + RemoveFirst(); + return true; + } + + SinglyLinkedListNode current = head; + + while (current.Next != head) + { + if (comparer.Equals(current.Next.Value, item)) + { + if (current.Next == _tail) + { + _tail = current; + } + + current.Next = current.Next.Next; + + _count--; + _version++; + + return true; + } + + current = current.Next; + } + + return false; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.RemoveFirst.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.RemoveFirst.cs new file mode 100644 index 0000000..cdcaa87 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.RemoveFirst.cs @@ -0,0 +1,29 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public void RemoveFirst() + { + if (_tail == null) + { + throw new InvalidOperationException("list is empty bro..."); + } + + if (_tail.Next == _tail) + { + _tail = null; + } + else + { + SinglyLinkedListNode head = _tail.Next; + _tail.Next = head.Next; + } + + _count--; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.RemoveLast.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.RemoveLast.cs new file mode 100644 index 0000000..7fe5d9f --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.RemoveLast.cs @@ -0,0 +1,36 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public void RemoveLast() + { + if (_tail == null) + { + throw new InvalidOperationException("HAHA! EMPTY..."); + } + + if (_tail.Next == _tail) + { + _tail = null; + } + else + { + SinglyLinkedListNode current = _tail.Next; + + while (current.Next != _tail) + { + current = current.Next; + } + + current.Next = _tail.Next; + _tail = current; + } + + _count--; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Reverse.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Reverse.cs new file mode 100644 index 0000000..a13f3c4 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.Reverse.cs @@ -0,0 +1,32 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public void Reverse() + { + if (_tail == null || _tail.Next == _tail) + { + return; + } + + SinglyLinkedListNode prev = _tail; + SinglyLinkedListNode current = Head; + SinglyLinkedListNode head = Head; + + do + { + SinglyLinkedListNode next = current.Next; + current.Next = prev; + prev = current; + current = next; + } + while (!ReferenceEquals(current, head)); + + _tail = head; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.ReverseIterator.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.ReverseIterator.cs new file mode 100644 index 0000000..230f294 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.ReverseIterator.cs @@ -0,0 +1,33 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides implementation +/// for . +/// +public partial class CircularLinkedList +{ + /// + public IEnumerable ReverseIterator() + { + if (_tail == null) + { + yield break; + } + + Stack stack = new Stack(); + SinglyLinkedListNode current = Head; + SinglyLinkedListNode start = current; + + do + { + stack.Push(current.Value); + current = current.Next; + } + while (!ReferenceEquals(current, start)); + + while (stack.Count > 0) + { + yield return stack.Pop(); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.ToArray.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.ToArray.cs new file mode 100644 index 0000000..83af956 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.ToArray.cs @@ -0,0 +1,28 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class CircularLinkedList +{ + /// + public T[] ToArray() + { + T[] array = new T[_count]; + + if (_tail == null) + { + return array; + } + + SinglyLinkedListNode current = Head; + + for (int i = 0; i < _count; i++) + { + array[i] = current.Value; + current = current.Next; + } + + return array; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.cs b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.cs new file mode 100644 index 0000000..5cccc2e --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/CircularLinkedList.cs @@ -0,0 +1,26 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Represents a circular singly linked list implementation of . +/// The list maintains a reference to the tail node; the head is tail.Next. +/// +/// The element type. +public partial class CircularLinkedList : ILinkedList +{ + private SinglyLinkedListNode _tail; + private int _count; + private int _version; + + private SinglyLinkedListNode Head + { + get + { + if (_tail == null) + { + return null; + } + + return _tail.Next; + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddFirst.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddFirst.cs new file mode 100644 index 0000000..66b85c6 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddFirst.cs @@ -0,0 +1,28 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public void AddFirst(T item) + { + LinkedListNode newNode = new LinkedListNode(item); + + if (_head == null) + { + _head = newNode; + _tail = newNode; + } + else + { + newNode.Next = _head; + _head.Prev = newNode; + _head = newNode; + } + + _count++; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddLast.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddLast.cs new file mode 100644 index 0000000..8b49004 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddLast.cs @@ -0,0 +1,28 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public void AddLast(T item) + { + LinkedListNode newNode = new LinkedListNode(item); + + if (_tail == null) + { + _head = newNode; + _tail = newNode; + } + else + { + newNode.Prev = _tail; + _tail.Next = newNode; + _tail = newNode; + } + + _count++; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddRange.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddRange.cs new file mode 100644 index 0000000..5e3ad58 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.AddRange.cs @@ -0,0 +1,19 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method +/// for . +/// +public partial class DoublyLinkedList +{ + /// + public void AddRange(IEnumerable items) + { + ArgumentNullException.ThrowIfNull(items); + + foreach (T item in items) + { + AddLast(item); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Clear.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Clear.cs new file mode 100644 index 0000000..d0fdc34 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Clear.cs @@ -0,0 +1,16 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public void Clear() + { + _head = null; + _tail = null; + _count = 0; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Clone.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Clone.cs new file mode 100644 index 0000000..3f0cfdb --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Clone.cs @@ -0,0 +1,22 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public ILinkedList Clone() + { + DoublyLinkedList clone = new DoublyLinkedList(); + LinkedListNode current = _head; + + while (current != null) + { + clone.AddLast(current.Value); + current = current.Next; + } + + return clone; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Contains.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Contains.cs new file mode 100644 index 0000000..e46aebd --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Contains.cs @@ -0,0 +1,13 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public bool Contains(T item) + { + return Find(item) != null; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Count.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Count.cs new file mode 100644 index 0000000..d5d01c6 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Count.cs @@ -0,0 +1,13 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the property for . +/// +public partial class DoublyLinkedList +{ + /// + public int Count + { + get { return _count; } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Enumeration.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Enumeration.cs new file mode 100644 index 0000000..6225b41 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Enumeration.cs @@ -0,0 +1,20 @@ +using System.Collections; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides enumeration for . +/// +public partial class DoublyLinkedList +{ + /// + public IEnumerator GetEnumerator() + { + return new DoublyLinkedListEnumerator(_head, () => _version); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Find.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Find.cs new file mode 100644 index 0000000..a240e9f --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Find.cs @@ -0,0 +1,25 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides internal search helpers for . +/// +public partial class DoublyLinkedList +{ + private LinkedListNode Find(T item) + { + LinkedListNode current = _head; + EqualityComparer comparer = EqualityComparer.Default; + + while (current != null) + { + if (comparer.Equals(current.Value, item)) + { + return current; + } + + current = current.Next; + } + + return null; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.GetNodeDepth.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.GetNodeDepth.cs new file mode 100644 index 0000000..775f064 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.GetNodeDepth.cs @@ -0,0 +1,30 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the implementation +/// for . +/// +public partial class DoublyLinkedList +{ + /// + public int GetNodeDepth(T item) + { + LinkedListNode node = Find(item); + + if (node == null) + { + return -1; + } + + int depth = 0; + LinkedListNode current = node; + + while (current.Prev != null) + { + depth++; + current = current.Prev; + } + + return depth; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.GetStructuralInfo.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.GetStructuralInfo.cs new file mode 100644 index 0000000..217a234 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.GetStructuralInfo.cs @@ -0,0 +1,30 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the implementation +/// for . +/// +public partial class DoublyLinkedList +{ + /// + public (int Length, int MidIndex) GetStructuralInfo() + { + if (_head == null) + { + return (0, -1); + } + + LinkedListNode slow = _head; + LinkedListNode fast = _head; + int index = 0; + + while (fast != null && fast.Next != null) + { + slow = slow.Next; + fast = fast.Next.Next; + index++; + } + + return (_count, index); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.HasCycle.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.HasCycle.cs new file mode 100644 index 0000000..11026bd --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.HasCycle.cs @@ -0,0 +1,32 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public bool HasCycle() + { + if (_head == null) + { + return false; + } + + LinkedListNode slow = _head; + LinkedListNode fast = _head; + + while (fast != null && fast.Next != null) + { + slow = slow.Next; + fast = fast.Next.Next; + + if (ReferenceEquals(slow, fast)) + { + return true; + } + } + + return false; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.PeekFirst.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.PeekFirst.cs new file mode 100644 index 0000000..9ddf287 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.PeekFirst.cs @@ -0,0 +1,18 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public T PeekFirst() + { + if (_head == null) + { + throw new InvalidOperationException("List is empty."); + } + + return _head.Value; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.PeekLast.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.PeekLast.cs new file mode 100644 index 0000000..25ac9e5 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.PeekLast.cs @@ -0,0 +1,18 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public T PeekLast() + { + if (_tail == null) + { + throw new InvalidOperationException("List is empty."); + } + + return _tail.Value; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Remove.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Remove.cs new file mode 100644 index 0000000..92d9491 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Remove.cs @@ -0,0 +1,36 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public bool Remove(T item) + { + LinkedListNode node = Find(item); + + if (node == null) + { + return false; + } + + if (node == _head) + { + RemoveFirst(); + } + else if (node == _tail) + { + RemoveLast(); + } + else + { + node.Prev.Next = node.Next; + node.Next.Prev = node.Prev; + _count--; + _version++; + } + + return true; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.RemoveFirst.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.RemoveFirst.cs new file mode 100644 index 0000000..04656c3 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.RemoveFirst.cs @@ -0,0 +1,30 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public void RemoveFirst() + { + if (_head == null) + { + throw new InvalidOperationException("List is empty."); + } + + if (_head == _tail) + { + _head = null; + _tail = null; + } + else + { + _head = _head.Next; + _head.Prev = null; + } + + _count--; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.RemoveLast.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.RemoveLast.cs new file mode 100644 index 0000000..0d9466c --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.RemoveLast.cs @@ -0,0 +1,30 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public void RemoveLast() + { + if (_tail == null) + { + throw new InvalidOperationException("List is empty."); + } + + if (_head == _tail) + { + _head = null; + _tail = null; + } + else + { + _tail = _tail.Prev; + _tail.Next = null; + } + + _count--; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Reverse.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Reverse.cs new file mode 100644 index 0000000..cafdfef --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.Reverse.cs @@ -0,0 +1,34 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public void Reverse() + { + if (_head == null || _head == _tail) + { + return; + } + + LinkedListNode current = _head; + _tail = _head; + LinkedListNode temp = null; + + while (current != null) + { + temp = current.Prev; + current.Prev = current.Next; + current.Next = temp; + current = current.Prev; + } + + if (temp != null) + { + _head = temp.Prev; + _version++; + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.ReverseIterator.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.ReverseIterator.cs new file mode 100644 index 0000000..7a7c5fe --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.ReverseIterator.cs @@ -0,0 +1,20 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides implementation +/// for . +/// +public partial class DoublyLinkedList +{ + /// + public IEnumerable ReverseIterator() + { + LinkedListNode current = _tail; + + while (current != null) + { + yield return current.Value; + current = current.Prev; + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.ToArray.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.ToArray.cs new file mode 100644 index 0000000..09dfad9 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.ToArray.cs @@ -0,0 +1,22 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class DoublyLinkedList +{ + /// + public T[] ToArray() + { + T[] array = new T[_count]; + LinkedListNode current = _head; + + for (int i = 0; i < _count; i++) + { + array[i] = current.Value; + current = current.Next; + } + + return array; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.cs new file mode 100644 index 0000000..3f9f112 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedList.cs @@ -0,0 +1,13 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Represents a doubly linked list implementation of . +/// +/// The element type. +public partial class DoublyLinkedList : ILinkedList +{ + private LinkedListNode _head; + private LinkedListNode _tail; + private int _count; + private int _version; +} diff --git a/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedListEnumerator.cs b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedListEnumerator.cs new file mode 100644 index 0000000..64c74f5 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/DoublyLinkedListEnumerator.cs @@ -0,0 +1,84 @@ +using System.Collections; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Enumerates the elements of a doubly linked list with version checking. +/// +/// The element type. +public sealed class DoublyLinkedListEnumerator : IEnumerator +{ + private readonly LinkedListNode _start; + private readonly Func _getVersion; + private readonly int _initialVersion; + + private LinkedListNode _current; + + /// + /// Initializes a new instance of the class. + /// + /// The first node of the list. + /// + /// A delegate that returns the current version of the underlying list. + /// If , a constant zero is used. + /// + public DoublyLinkedListEnumerator( + LinkedListNode start, + Func getVersion = null) + { + _start = start; + _getVersion = getVersion ?? (() => 0); + _initialVersion = _getVersion(); + } + + /// + public T Current + { + get + { + if (_current == null) + { + throw new InvalidOperationException("Enumerator is not positioned on an element."); + } + + return _current.Value; + } + } + + object IEnumerator.Current => Current; + + /// + public bool MoveNext() + { + if (_initialVersion != _getVersion()) + { + throw new InvalidOperationException("Collection was modified."); + } + + if (_current == null) + { + _current = _start; + return _current != null; + } + + _current = _current.Next; + return _current != null; + } + + /// + public void Reset() + { + if (_initialVersion != _getVersion()) + { + throw new InvalidOperationException("Collection was modified."); + } + + _current = null; + } + + /// + public void Dispose() + { + GC.SuppressFinalize(this); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/ILinkedList.cs b/src/Csdsa/DataStructures/LinkedLists/ILinkedList.cs new file mode 100644 index 0000000..d80a4aa --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/ILinkedList.cs @@ -0,0 +1,160 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Defines a common contract for linked list implementations. +/// +/// Concepts: +/// +/// +/// +/// Multiple linked list variants with specialized implementations. +/// +/// +/// +/// Interface-based abstraction that standardizes the API surface +/// across different list variants. +/// +/// +/// +/// +/// Strict separation of concerns: node types, core list, iterators, +/// and extension helpers. +/// +/// +/// +/// +/// Functional-style operators such as map, filter, reduce, foreach, and partition. +/// +/// +/// +/// +/// Thread-safety via synchronized wrappers and snapshot-based iteration. +/// +/// +/// +/// +/// Structural diagnostics including cycle detection and positional analysis. +/// +/// +/// +/// +/// The type of elements stored in the list. +public interface ILinkedList : IEnumerable +{ + /// + /// Inserts an element at the beginning of the list. + /// + /// The element to insert. + void AddFirst(T item); + + /// + /// Inserts an element at the end of the list. + /// + /// The element to insert. + void AddLast(T item); + + /// + /// Removes the first element of the list. + /// + void RemoveFirst(); + + /// + /// Removes the last element of the list. + /// + void RemoveLast(); + + /// + /// Removes the first occurrence of a specific element from the list. + /// + /// The element to remove. + /// + /// if the element was found and removed; otherwise, . + /// + bool Remove(T item); + + /// + /// Determines whether the list contains a specific value. + /// + /// The element to locate. + /// + /// if the element is found; otherwise, . + /// + bool Contains(T item); + + /// + /// Gets the number of elements contained in the list. + /// + int Count { get; } + + /// + /// Returns the first element in the list without removing it. + /// + /// The first element in the list. + T PeekFirst(); + + /// + /// Returns the last element in the list without removing it. + /// + /// The last element in the list. + T PeekLast(); + + /// + /// Removes all elements from the list. + /// + void Clear(); + + /// + /// Reverses the order of the elements in the list in-place. + /// + void Reverse(); + + /// + /// Creates a shallow copy of the list. + /// + /// A new that contains the same elements. + ILinkedList Clone(); + + /// + /// Appends the elements of the specified sequence to the end of the list. + /// + /// The sequence whose elements should be added. + void AddRange(IEnumerable items); + + /// + /// Copies the elements of the list to a new array. + /// + /// An array containing copies of the elements of the list. + T[] ToArray(); + + /// + /// Determines whether the list contains a structural cycle. + /// + /// + /// if the list contains a cycle; otherwise, . + /// + bool HasCycle(); + + /// + /// Returns an enumerable that yields the elements of the list in reverse order. + /// + /// An that iterates the list in reverse. + IEnumerable ReverseIterator(); + + /// + /// Gets diagnostic information about the structure of the list. + /// + /// + /// A tuple whose Length is the number of elements and whose MidIndex + /// is the index of the middle element, or -1 if the list is empty. + /// + (int Length, int MidIndex) GetStructuralInfo(); + + /// + /// Gets the zero-based index of the first node whose value equals the specified item. + /// + /// The value to locate. + /// + /// The zero-based index of the node if found; otherwise, -1. + /// + int GetNodeDepth(T item); +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.AsReadOnly.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.AsReadOnly.cs new file mode 100644 index 0000000..2fdc87b --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.AsReadOnly.cs @@ -0,0 +1,60 @@ +using System.Collections; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the AsReadOnly extension for . +/// +public static partial class LinkedListExtensions +{ + /// + /// Creates a read-only wrapper around the specified linked list. + /// + /// The element type. + /// The list to wrap. + /// + /// An that provides read-only access + /// to the underlying list. + /// + /// + /// Thrown when is null. + /// + public static IReadOnlyCollection AsReadOnly(this ILinkedList list) + { + if (list == null) + { + ArgumentNullException.ThrowIfNull(list); + } + + return new ReadOnlyLinkedListWrapper(list); + } + + /// + /// Read-only wrapper around an . + /// + /// The element type. + private sealed class ReadOnlyLinkedListWrapper : IReadOnlyCollection + { + private readonly ILinkedList _inner; + + public ReadOnlyLinkedListWrapper(ILinkedList inner) + { + _inner = inner; + } + + public int Count + { + get { return _inner.Count; } + } + + public IEnumerator GetEnumerator() + { + return _inner.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.DebugPrint.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.DebugPrint.cs new file mode 100644 index 0000000..7539b49 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.DebugPrint.cs @@ -0,0 +1,36 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the DebugPrint extension for . +/// +public static partial class LinkedListExtensions +{ + /// + /// Writes diagnostic information about the linked list to the console. + /// + /// The element type. + /// The list to inspect. + /// + /// Thrown when is null. + /// + public static void DebugPrint(this ILinkedList list) + { + if (list == null) + { + ArgumentNullException.ThrowIfNull(list); + } + + Console.WriteLine("LinkedList Count: " + list.Count); + Console.WriteLine("Has Cycle: " + list.HasCycle()); + + (int length, int midIndex) = list.GetStructuralInfo(); + Console.WriteLine("Structural Info - Length: " + length + ", Mid Index: " + midIndex); + + int index = 0; + foreach (T item in list) + { + Console.WriteLine("[" + index + "]: " + item); + index++; + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Filter.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Filter.cs new file mode 100644 index 0000000..ddbb335 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Filter.cs @@ -0,0 +1,43 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the Filter extension for . +/// +public static partial class LinkedListExtensions +{ + /// + /// Filters the elements of the list based on a predicate. + /// + /// The element type. + /// The list to filter. + /// A function to test each element for a condition. + /// + /// An that contains elements from the input list + /// that satisfy the condition. + /// + /// + /// Thrown when or is null. + /// + public static IEnumerable Filter( + this ILinkedList list, + Func predicate) + { + if (list == null) + { + ArgumentNullException.ThrowIfNull(list); + } + + if (predicate == null) + { + ArgumentNullException.ThrowIfNull(predicate); + } + + foreach (T item in list) + { + if (predicate(item)) + { + yield return item; + } + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.ForEach.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.ForEach.cs new file mode 100644 index 0000000..869bf5e --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.ForEach.cs @@ -0,0 +1,36 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the ForEach extension for . +/// +public static partial class LinkedListExtensions +{ + /// + /// Performs the specified action on each element of the list. + /// + /// The element type. + /// The list whose elements to process. + /// The action to perform on each element. + /// + /// Thrown when or is null. + /// + public static void ForEach( + this ILinkedList list, + Action action) + { + if (list == null) + { + ArgumentNullException.ThrowIfNull(list); + } + + if (action == null) + { + ArgumentNullException.ThrowIfNull(action); + } + + foreach (T item in list) + { + action(item); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Map.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Map.cs new file mode 100644 index 0000000..2ef6314 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Map.cs @@ -0,0 +1,41 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the Map extension for . +/// +public static partial class LinkedListExtensions +{ + /// + /// Projects each element of the linked list into a new form. + /// + /// The source element type. + /// The result element type. + /// The list whose elements to transform. + /// A transform function to apply to each element. + /// + /// An whose elements are the result of + /// invoking the transform function on each element of the source list. + /// + /// + /// Thrown when or is null. + /// + public static IEnumerable Map( + this ILinkedList list, + Func selector) + { + if (selector == null) + { + ArgumentNullException.ThrowIfNull(selector); + } + + if (list == null) + { + ArgumentNullException.ThrowIfNull(list); + } + + foreach (T item in list) + { + yield return selector(item); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Partition.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Partition.cs new file mode 100644 index 0000000..b255ff2 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Partition.cs @@ -0,0 +1,52 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the Partition extension for . +/// +public static partial class LinkedListExtensions +{ + /// + /// Partitions the elements of the list into two linked lists based on a predicate. + /// + /// The element type. + /// The list to partition. + /// The predicate used to partition elements. + /// + /// A tuple where Matches contains elements that satisfy the predicate and + /// NonMatches contains elements that do not. + /// + /// + /// Thrown when or is null. + /// + public static (ILinkedList Matches, ILinkedList NonMatches) Partition( + this ILinkedList list, + Func predicate) + { + if (list == null) + { + ArgumentNullException.ThrowIfNull(list); + } + + if (predicate == null) + { + ArgumentNullException.ThrowIfNull(predicate); + } + + DoublyLinkedList matches = new DoublyLinkedList(); + DoublyLinkedList nonMatches = new DoublyLinkedList(); + + foreach (T item in list) + { + if (predicate(item)) + { + matches.AddLast(item); + } + else + { + nonMatches.AddLast(item); + } + } + + return (Matches: matches, NonMatches: nonMatches); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Reduce.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Reduce.cs new file mode 100644 index 0000000..3662f2f --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Reduce.cs @@ -0,0 +1,46 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the Reduce extension for . +/// +public static partial class LinkedListExtensions +{ + /// + /// Aggregates the elements of the list using the specified seed value and accumulator function. + /// + /// The element type. + /// The result type. + /// The list whose elements to aggregate. + /// The initial accumulator value. + /// + /// A function that updates the accumulator with each element. + /// + /// The final accumulator value. + /// + /// Thrown when or is null. + /// + public static TResult Reduce( + this ILinkedList list, + TResult seed, + Func accumulator) + { + if (list == null) + { + ArgumentNullException.ThrowIfNull(list); + } + + if (accumulator == null) + { + ArgumentNullException.ThrowIfNull(accumulator); + } + + TResult result = seed; + + foreach (T item in list) + { + result = accumulator(result, item); + } + + return result; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Synchronized.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Synchronized.cs new file mode 100644 index 0000000..fcbb723 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.Synchronized.cs @@ -0,0 +1,212 @@ +using System.Collections; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the Synchronized extension for . +/// +public static partial class LinkedListExtensions +{ + /// + /// Creates a thread-safe wrapper around the specified linked list. + /// + /// The element type. + /// The list to wrap. + /// + /// An that is safe for concurrent access via locking. + /// + /// + /// Thrown when is null. + /// + public static ILinkedList Synchronized(this ILinkedList list) + { + if (list == null) + { + ArgumentNullException.ThrowIfNull(list); + } + + return new SynchronizedLinkedList(list); + } + + /// + /// Thread-safe wrapper around an using a monitor lock. + /// + /// The element type. + private sealed class SynchronizedLinkedList : ILinkedList + { + private readonly ILinkedList _inner; + private readonly object _lockObject; + + public SynchronizedLinkedList(ILinkedList inner) + { + _inner = inner; + _lockObject = new object(); + } + + public int Count + { + get + { + lock (_lockObject) + { + return _inner.Count; + } + } + } + + public void AddFirst(T item) + { + lock (_lockObject) + { + _inner.AddFirst(item); + } + } + + public void AddLast(T item) + { + lock (_lockObject) + { + _inner.AddLast(item); + } + } + + public void Clear() + { + lock (_lockObject) + { + _inner.Clear(); + } + } + + public bool Contains(T item) + { + lock (_lockObject) + { + return _inner.Contains(item); + } + } + + public T PeekFirst() + { + lock (_lockObject) + { + return _inner.PeekFirst(); + } + } + + public T PeekLast() + { + lock (_lockObject) + { + return _inner.PeekLast(); + } + } + + public void RemoveFirst() + { + lock (_lockObject) + { + _inner.RemoveFirst(); + } + } + + public void RemoveLast() + { + lock (_lockObject) + { + _inner.RemoveLast(); + } + } + + public bool Remove(T item) + { + lock (_lockObject) + { + return _inner.Remove(item); + } + } + + public void Reverse() + { + lock (_lockObject) + { + _inner.Reverse(); + } + } + + public ILinkedList Clone() + { + lock (_lockObject) + { + return _inner.Clone(); + } + } + + public void AddRange(IEnumerable items) + { + lock (_lockObject) + { + _inner.AddRange(items); + } + } + + public T[] ToArray() + { + lock (_lockObject) + { + // Snapshot via enumeration to preserve original behavior. + List snapshot = new List(_inner); + return snapshot.ToArray(); + } + } + + public bool HasCycle() + { + lock (_lockObject) + { + return _inner.HasCycle(); + } + } + + public IEnumerable ReverseIterator() + { + lock (_lockObject) + { + return _inner.ReverseIterator(); + } + } + + public (int Length, int MidIndex) GetStructuralInfo() + { + lock (_lockObject) + { + return _inner.GetStructuralInfo(); + } + } + + public int GetNodeDepth(T item) + { + lock (_lockObject) + { + return _inner.GetNodeDepth(item); + } + } + + public IEnumerator GetEnumerator() + { + T[] snapshot; + lock (_lockObject) + { + List list = new List(_inner); + snapshot = list.ToArray(); + } + + return ((IEnumerable)snapshot).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.cs new file mode 100644 index 0000000..583abe7 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListExtensions.cs @@ -0,0 +1,12 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides functional-style and utility extensions for . +/// +/// Includes map, filter, reduce, foreach, partition, synchronized wrappers, +/// read-only views, and diagnostic printing. +/// +/// +public static partial class LinkedListExtensions +{ +} diff --git a/src/Csdsa/DataStructures/LinkedLists/LinkedListNode.cs b/src/Csdsa/DataStructures/LinkedLists/LinkedListNode.cs new file mode 100644 index 0000000..11954a1 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/LinkedListNode.cs @@ -0,0 +1,33 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Represents a node in a doubly linked list. +/// +/// The type of the value stored in the node. +public class LinkedListNode +{ + /// + /// Initializes a new instance of the class + /// with the specified value. + /// + /// The value stored in the node. + public LinkedListNode(T value) + { + Value = value; + } + + /// + /// Gets or sets the value stored in the node. + /// + public T Value { get; set; } + + /// + /// Gets or sets the next node in the list. + /// + public LinkedListNode Next { get; set; } + + /// + /// Gets or sets the previous node in the list. + /// + public LinkedListNode Prev { get; set; } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedLisst.Contains.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedLisst.Contains.cs new file mode 100644 index 0000000..75703a6 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedLisst.Contains.cs @@ -0,0 +1,26 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public bool Contains(T item) + { + SinglyLinkedListNode current = _head; + EqualityComparer comparer = EqualityComparer.Default; + + while (current != null) + { + if (comparer.Equals(current.Value, item)) + { + return true; + } + + current = current.Next; + } + + return false; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddFirst.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddFirst.cs new file mode 100644 index 0000000..41f67ef --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddFirst.cs @@ -0,0 +1,27 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public void AddFirst(T item) + { + SinglyLinkedListNode newNode = new SinglyLinkedListNode(item); + + if (_head == null) + { + _head = newNode; + _tail = newNode; + } + else + { + newNode.Next = _head; + _head = newNode; + } + + _count++; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddLast.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddLast.cs new file mode 100644 index 0000000..c730f5c --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddLast.cs @@ -0,0 +1,27 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public void AddLast(T item) + { + SinglyLinkedListNode newNode = new SinglyLinkedListNode(item); + + if (_tail == null) + { + _head = newNode; + _tail = newNode; + } + else + { + _tail.Next = newNode; + _tail = newNode; + } + + _count++; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddRange.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddRange.cs new file mode 100644 index 0000000..75900f1 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.AddRange.cs @@ -0,0 +1,22 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method +/// for . +/// +public partial class SinglyLinkedList +{ + /// + public void AddRange(IEnumerable items) + { + if (items == null) + { + ArgumentNullException.ThrowIfNull(items); + } + + foreach (T item in items) + { + AddLast(item); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Clear.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Clear.cs new file mode 100644 index 0000000..cf018cb --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Clear.cs @@ -0,0 +1,16 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public void Clear() + { + _head = null; + _tail = null; + _count = 0; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Clone.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Clone.cs new file mode 100644 index 0000000..aea1060 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Clone.cs @@ -0,0 +1,22 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public ILinkedList Clone() + { + SinglyLinkedList clone = new SinglyLinkedList(); + SinglyLinkedListNode current = _head; + + while (current != null) + { + clone.AddLast(current.Value); + current = current.Next; + } + + return clone; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Count.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Count.cs new file mode 100644 index 0000000..c5b0450 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Count.cs @@ -0,0 +1,13 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the property for . +/// +public partial class SinglyLinkedList +{ + /// + public int Count + { + get { return _count; } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Enumeration.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Enumeration.cs new file mode 100644 index 0000000..c802fbb --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Enumeration.cs @@ -0,0 +1,20 @@ +using System.Collections; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides enumeration for . +/// +public partial class SinglyLinkedList +{ + /// + public IEnumerator GetEnumerator() + { + return new SinglyLinkedListEnumerator(_head, () => _version); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.GetStructuralInfo.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.GetStructuralInfo.cs new file mode 100644 index 0000000..1966023 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.GetStructuralInfo.cs @@ -0,0 +1,30 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the implementation +/// for . +/// +public partial class SinglyLinkedList +{ + /// + public (int Length, int MidIndex) GetStructuralInfo() + { + if (_head == null) + { + return (0, -1); + } + + SinglyLinkedListNode slow = _head; + SinglyLinkedListNode fast = _head; + int index = 0; + + while (fast != null && fast.Next != null) + { + slow = slow.Next; + fast = fast.Next.Next; + index++; + } + + return (_count, index); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.HasCycle.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.HasCycle.cs new file mode 100644 index 0000000..852ab50 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.HasCycle.cs @@ -0,0 +1,32 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public bool HasCycle() + { + if (_head == null) + { + return false; + } + + SinglyLinkedListNode slow = _head; + SinglyLinkedListNode fast = _head; + + while (fast != null && fast.Next != null) + { + slow = slow.Next; + fast = fast.Next.Next; + + if (ReferenceEquals(slow, fast)) + { + return true; + } + } + + return false; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.PeekFirst.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.PeekFirst.cs new file mode 100644 index 0000000..7bf870c --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.PeekFirst.cs @@ -0,0 +1,18 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public T PeekFirst() + { + if (_head == null) + { + throw new InvalidOperationException("List is empty."); + } + + return _head.Value; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.PeekLast.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.PeekLast.cs new file mode 100644 index 0000000..33330cc --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.PeekLast.cs @@ -0,0 +1,18 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public T PeekLast() + { + if (_tail == null) + { + throw new InvalidOperationException("List is empty."); + } + + return _tail.Value; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Remove.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Remove.cs new file mode 100644 index 0000000..8aa84b0 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Remove.cs @@ -0,0 +1,48 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public bool Remove(T item) + { + if (_head == null) + { + return false; + } + + EqualityComparer comparer = EqualityComparer.Default; + + if (comparer.Equals(_head.Value, item)) + { + RemoveFirst(); + return true; + } + + SinglyLinkedListNode current = _head; + + while (current.Next != null) + { + if (comparer.Equals(current.Next.Value, item)) + { + if (current.Next == _tail) + { + _tail = current; + } + + current.Next = current.Next.Next; + + _count--; + _version++; + + return true; + } + + current = current.Next; + } + + return false; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.RemoveFirst.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.RemoveFirst.cs new file mode 100644 index 0000000..0bd74c2 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.RemoveFirst.cs @@ -0,0 +1,26 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public void RemoveFirst() + { + if (_head == null) + { + throw new InvalidOperationException("List is empty."); + } + + _head = _head.Next; + + if (_head == null) + { + _tail = null; + } + + _count--; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.RemoveLast.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.RemoveLast.cs new file mode 100644 index 0000000..7a01e4c --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.RemoveLast.cs @@ -0,0 +1,37 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public void RemoveLast() + { + if (_tail == null) + { + throw new InvalidOperationException("List is empty."); + } + + if (_head == _tail) + { + _head = null; + _tail = null; + } + else + { + SinglyLinkedListNode current = _head; + + while (current.Next != _tail) + { + current = current.Next; + } + + current.Next = null; + _tail = current; + } + + _count--; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Reverse.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Reverse.cs new file mode 100644 index 0000000..a203428 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.Reverse.cs @@ -0,0 +1,31 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public void Reverse() + { + if (_head == null || _head == _tail) + { + return; + } + + SinglyLinkedListNode previous = null; + SinglyLinkedListNode current = _head; + _tail = _head; + + while (current != null) + { + SinglyLinkedListNode next = current.Next; + current.Next = previous; + previous = current; + current = next; + } + + _head = previous; + _version++; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.ReverseIterator.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.ReverseIterator.cs new file mode 100644 index 0000000..e8fe927 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.ReverseIterator.cs @@ -0,0 +1,26 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides implementation +/// for . +/// +public partial class SinglyLinkedList +{ + /// + public IEnumerable ReverseIterator() + { + Stack stack = new Stack(); + SinglyLinkedListNode current = _head; + + while (current != null) + { + stack.Push(current.Value); + current = current.Next; + } + + while (stack.Count > 0) + { + yield return stack.Pop(); + } + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.ToArray.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.ToArray.cs new file mode 100644 index 0000000..703a318 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.ToArray.cs @@ -0,0 +1,22 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the method for . +/// +public partial class SinglyLinkedList +{ + /// + public T[] ToArray() + { + T[] array = new T[_count]; + SinglyLinkedListNode current = _head; + + for (int i = 0; i < _count; i++) + { + array[i] = current.Value; + current = current.Next; + } + + return array; + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.cs new file mode 100644 index 0000000..64e8db5 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedList.cs @@ -0,0 +1,13 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Represents a singly linked list implementation of . +/// +/// The element type. +public partial class SinglyLinkedList : ILinkedList +{ + private SinglyLinkedListNode _head; + private SinglyLinkedListNode _tail; + private int _count; + private int _version; +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedListEnumerator.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedListEnumerator.cs new file mode 100644 index 0000000..72ed875 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedListEnumerator.cs @@ -0,0 +1,84 @@ +using System.Collections; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Enumerates the elements of a singly linked list with version checking. +/// +/// The element type. +public sealed class SinglyLinkedListEnumerator : IEnumerator +{ + private readonly SinglyLinkedListNode _start; + private readonly Func _getVersion; + private readonly int _initialVersion; + + private SinglyLinkedListNode _current; + + /// + /// Initializes a new instance of the class. + /// + /// The first node of the list. + /// + /// A delegate that returns the current version of the underlying list. + /// If , a constant zero is used. + /// + public SinglyLinkedListEnumerator( + SinglyLinkedListNode start, + Func getVersion = null) + { + _start = start; + _getVersion = getVersion ?? (() => 0); + _initialVersion = _getVersion(); + } + + /// + public T Current + { + get + { + if (_current == null) + { + throw new InvalidOperationException("Enumerator is not positioned on an element."); + } + + return _current.Value; + } + } + + object IEnumerator.Current => Current; + + /// + public bool MoveNext() + { + if (_initialVersion != _getVersion()) + { + throw new InvalidOperationException("Collection was modified."); + } + + if (_current == null) + { + _current = _start; + return _current != null; + } + + _current = _current.Next; + return _current != null; + } + + /// + public void Reset() + { + if (_initialVersion != _getVersion()) + { + throw new InvalidOperationException("Collection was modified."); + } + + _current = null; + } + + /// + public void Dispose() + { + GC.SuppressFinalize(this); + } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedListNode.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedListNode.cs new file mode 100644 index 0000000..ce45cc2 --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedListNode.cs @@ -0,0 +1,28 @@ +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Represents a node in a singly linked list. +/// +/// The type of the value stored in the node. +public class SinglyLinkedListNode +{ + /// + /// Initializes a new instance of the class + /// with the specified value. + /// + /// The value stored in the node. + public SinglyLinkedListNode(T value) + { + Value = value; + } + + /// + /// Gets or sets the value stored in the node. + /// + public T Value { get; set; } + + /// + /// Gets or sets the next node in the list. + /// + public SinglyLinkedListNode Next { get; set; } +} diff --git a/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedLists.GetNodeDepth.cs b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedLists.GetNodeDepth.cs new file mode 100644 index 0000000..dd0a40f --- /dev/null +++ b/src/Csdsa/DataStructures/LinkedLists/SinglyLinkedLists.GetNodeDepth.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace Csdsa.DataStructures.LinkedLists; + +/// +/// Provides the implementation +/// for . +/// +public partial class SinglyLinkedList +{ + /// + public int GetNodeDepth(T item) + { + int depth = 0; + SinglyLinkedListNode current = _head; + EqualityComparer comparer = EqualityComparer.Default; + + while (current != null) + { + if (comparer.Equals(current.Value, item)) + { + return depth; + } + + depth++; + current = current.Next; + } + + return -1; + } +} From fdece7e97056a061a2909993446a01514523bee9 Mon Sep 17 00:00:00 2001 From: mavantgarderc Date: Fri, 5 Dec 2025 21:54:18 +0330 Subject: [PATCH 2/2] DataStructure(LinkedList) --- .../DoublyLinkedList.AddRange.Tests.cs | 19 ++++++++ .../DoublyLinkedList.BasicOperation.Tests.cs | 29 ++++++++++++ .../DoublyLinkedList.Clear.Tests.cs | 25 +++++++++++ .../DoublyLinkedList.Clone.Tests.cs | 28 ++++++++++++ .../DoublyLinkedList.GetNodeDepth.Tests.cs | 24 ++++++++++ ...oublyLinkedList.GetStructuralInfo.Tests.cs | 30 +++++++++++++ .../DoublyLinkedList.PeekAndRemove.Tests.cs | 42 ++++++++++++++++++ .../DoublyLinkedList.Reverse.Tests.cs | 31 +++++++++++++ .../LinkedListExtensions.Functional.Tests.cs | 44 +++++++++++++++++++ 9 files changed, 272 insertions(+) create mode 100644 tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.AddRange.Tests.cs create mode 100644 tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.BasicOperation.Tests.cs create mode 100644 tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Clear.Tests.cs create mode 100644 tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Clone.Tests.cs create mode 100644 tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.GetNodeDepth.Tests.cs create mode 100644 tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.GetStructuralInfo.Tests.cs create mode 100644 tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.PeekAndRemove.Tests.cs create mode 100644 tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Reverse.Tests.cs create mode 100644 tests/Csdsa.Tests/DataStructures/LinkedLists/LinkedListExtensions.Functional.Tests.cs diff --git a/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.AddRange.Tests.cs b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.AddRange.Tests.cs new file mode 100644 index 0000000..0fb7d9f --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.AddRange.Tests.cs @@ -0,0 +1,19 @@ +using Csdsa.DataStructures.LinkedLists; +using Xunit; + +namespace Csdsa.Tests.DataStructures.LinkedLists; + +public class DoublyLinkedListAddRangeTests +{ + private static readonly string[] ExpectedAbc = { "a", "b", "c" }; + + [Fact] + public void AddRange_Appends_All_Items() + { + DoublyLinkedList list = new DoublyLinkedList(); + + list.AddRange(new[] { "a", "b", "c" }); + + Assert.Equal(ExpectedAbc, list.ToArray()); + } +} diff --git a/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.BasicOperation.Tests.cs b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.BasicOperation.Tests.cs new file mode 100644 index 0000000..f7790d5 --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.BasicOperation.Tests.cs @@ -0,0 +1,29 @@ +using System.Linq; +using Csdsa.DataStructures.LinkedLists; +using Xunit; + +namespace Csdsa.Tests.DataStructures.LinkedLists; + +public class DoublyLinkedListBasicOperationsTests +{ + private static readonly int[] Expected123 = { 1, 2, 3 }; + + [Fact] + public void AddFirst_AddLast_ToArray_And_Count_And_Contains_Work() + { + DoublyLinkedList list = new DoublyLinkedList(); + + Assert.Equal(0, list.Count); + + list.AddFirst(2); + list.AddFirst(1); + list.AddLast(3); + + Assert.Equal(3, list.Count); + + int[] arr = list.ToArray(); + Assert.Equal(Expected123, arr); + Assert.True(list.Contains(2)); + Assert.False(list.Contains(42)); + } +} diff --git a/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Clear.Tests.cs b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Clear.Tests.cs new file mode 100644 index 0000000..84618fc --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Clear.Tests.cs @@ -0,0 +1,25 @@ +using Csdsa.DataStructures.LinkedLists; +using Xunit; + +namespace Csdsa.Tests.DataStructures.LinkedLists; + +public class DoublyLinkedListClearTests +{ + private static DoublyLinkedList NewList(params int[] items) + { + DoublyLinkedList list = new DoublyLinkedList(); + list.AddRange(items); + return list; + } + + [Fact] + public void Clear_Empties_List() + { + DoublyLinkedList list = NewList(1, 2, 3); + + list.Clear(); + + Assert.Empty(list); + Assert.False(list.Contains(1)); + } +} diff --git a/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Clone.Tests.cs b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Clone.Tests.cs new file mode 100644 index 0000000..65e6c40 --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Clone.Tests.cs @@ -0,0 +1,28 @@ +using Csdsa.DataStructures.LinkedLists; +using Xunit; + +namespace Csdsa.Tests.DataStructures.LinkedLists; + +public class DoublyLinkedListCloneTests +{ + private static DoublyLinkedList NewList(params int[] items) + { + DoublyLinkedList list = new DoublyLinkedList(); + list.AddRange(items); + return list; + } + + [Fact] + public void Clone_Is_DeepCopy() + { + DoublyLinkedList original = NewList(5, 6, 7); + + DoublyLinkedList clone = (DoublyLinkedList)original.Clone(); + + Assert.Equal(original.ToArray(), clone.ToArray()); + + clone.AddLast(8); + + Assert.NotEqual(original.Count, clone.Count); + } +} diff --git a/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.GetNodeDepth.Tests.cs b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.GetNodeDepth.Tests.cs new file mode 100644 index 0000000..c5469a5 --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.GetNodeDepth.Tests.cs @@ -0,0 +1,24 @@ +using Csdsa.DataStructures.LinkedLists; +using Xunit; + +namespace Csdsa.Tests.DataStructures.LinkedLists; + +public class DoublyLinkedListGetNodeDepthTests +{ + private static DoublyLinkedList NewList(params int[] items) + { + DoublyLinkedList list = new DoublyLinkedList(); + list.AddRange(items); + return list; + } + + [Fact] + public void GetNodeDepth_Finds_Correct_Index_Or_NegativeOne() + { + DoublyLinkedList list = NewList(10, 20, 30); + + Assert.Equal(0, list.GetNodeDepth(10)); + Assert.Equal(2, list.GetNodeDepth(30)); + Assert.Equal(-1, list.GetNodeDepth(99)); + } +} diff --git a/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.GetStructuralInfo.Tests.cs b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.GetStructuralInfo.Tests.cs new file mode 100644 index 0000000..7e2572e --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.GetStructuralInfo.Tests.cs @@ -0,0 +1,30 @@ +using Csdsa.DataStructures.LinkedLists; +using Xunit; + +namespace Csdsa.Tests.DataStructures.LinkedLists; + +public class DoublyLinkedListGetStructuralInfoTests +{ + private static DoublyLinkedList NewList(params int[] items) + { + DoublyLinkedList list = new DoublyLinkedList(); + list.AddRange(items); + return list; + } + + [Theory] + [InlineData(new[] { 1, 2, 3 }, 3, 1)] + [InlineData(new[] { 1, 2, 3, 4 }, 4, 2)] + public void GetStructuralInfo_Returns_Correct_Length_And_Mid( + int[] data, + int expectedLength, + int expectedMidIndex) + { + DoublyLinkedList list = NewList(data); + + (int length, int mid) = list.GetStructuralInfo(); + + Assert.Equal(expectedLength, length); + Assert.Equal(expectedMidIndex, mid); + } +} diff --git a/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.PeekAndRemove.Tests.cs b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.PeekAndRemove.Tests.cs new file mode 100644 index 0000000..ec2243a --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.PeekAndRemove.Tests.cs @@ -0,0 +1,42 @@ +using System; +using Csdsa.DataStructures.LinkedLists; +using Xunit; + +namespace Csdsa.Tests.DataStructures.LinkedLists; + +public class DoublyLinkedListPeekAndRemoveTests +{ + private static DoublyLinkedList NewList(params int[] items) + { + DoublyLinkedList list = new DoublyLinkedList(); + list.AddRange(items); + return list; + } + + [Fact] + public void PeekFirst_PeekLast_And_RemoveMethods_Work_And_Throw_OnEmpty() + { + DoublyLinkedList list = NewList(10, 20, 30); + + Assert.Equal(10, list.PeekFirst()); + Assert.Equal(30, list.PeekLast()); + + list.RemoveFirst(); + Assert.Equal(2, list.Count); + Assert.Equal(20, list.PeekFirst()); + + list.RemoveLast(); + Assert.Single(list); + Assert.Equal(20, list.PeekLast()); + + bool removed = list.Remove(20); + Assert.True(removed); + Assert.Empty(list); + Assert.False(list.Remove(999)); + + Assert.Throws(() => list.RemoveFirst()); + Assert.Throws(() => list.RemoveLast()); + Assert.Throws(() => list.PeekFirst()); + Assert.Throws(() => list.PeekLast()); + } +} diff --git a/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Reverse.Tests.cs b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Reverse.Tests.cs new file mode 100644 index 0000000..dcc50f7 --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/LinkedLists/DoublyLinkedList.Reverse.Tests.cs @@ -0,0 +1,31 @@ +using System.Linq; +using Csdsa.DataStructures.LinkedLists; +using Xunit; + +namespace Csdsa.Tests.DataStructures.LinkedLists; + +public class DoublyLinkedListReverseTests +{ + private static readonly int[] Expected4321 = { 4, 3, 2, 1 }; + private static readonly int[] Expected1234 = { 1, 2, 3, 4 }; + + private static DoublyLinkedList NewList(params int[] items) + { + DoublyLinkedList list = new DoublyLinkedList(); + list.AddRange(items); + return list; + } + + [Fact] + public void Reverse_And_ReverseIterator_Work() + { + DoublyLinkedList list = NewList(1, 2, 3, 4); + + list.Reverse(); + + Assert.Equal(Expected4321, list.ToArray()); + + int[] back = list.ReverseIterator().Cast().ToArray(); + Assert.Equal(Expected1234, back); + } +} diff --git a/tests/Csdsa.Tests/DataStructures/LinkedLists/LinkedListExtensions.Functional.Tests.cs b/tests/Csdsa.Tests/DataStructures/LinkedLists/LinkedListExtensions.Functional.Tests.cs new file mode 100644 index 0000000..43fd3ae --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/LinkedLists/LinkedListExtensions.Functional.Tests.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Linq; +using Csdsa.DataStructures.LinkedLists; +using Xunit; + +namespace Csdsa.Tests.DataStructures.LinkedLists; + +public class LinkedListExtensionsFunctionalTests +{ + private static readonly int[] Expected1491625 = { 1, 4, 9, 16, 25 }; + private static readonly int[] Expected24 = { 2, 4 }; + private static readonly int[] Expected45 = { 4, 5 }; + private static readonly int[] Expected123 = { 1, 2, 3 }; + + private static DoublyLinkedList NewList(params int[] items) + { + DoublyLinkedList list = new DoublyLinkedList(); + list.AddRange(items); + return list; + } + + [Fact] + public void Map_Filter_Reduce_ForEach_And_Partition_Work_As_Expected() + { + DoublyLinkedList list = NewList(1, 2, 3, 4, 5); + + int[] squares = list.Map(x => x * x).Cast().ToArray(); + Assert.Equal(Expected1491625, squares); + + int[] evens = list.Filter(x => x % 2 == 0).Cast().ToArray(); + Assert.Equal(Expected24, evens); + + int sum = list.Reduce(0, (acc, value) => acc + value); + Assert.Equal(15, sum); + + List collected = new List(); + list.ForEach(collected.Add); + Assert.Equal(list.ToArray(), collected.ToArray()); + + (ILinkedList left, ILinkedList right) = list.Partition(x => x <= 3); + Assert.Equal(Expected123, left.ToArray()); + Assert.Equal(Expected45, right.ToArray()); + } +}