//Return the index of the last occurrence of the given item. Starting from the index start. O(n) public int LastIndexOf(Object item, int start, int count) { if (start < 0 || start >= _size) { throw new ArgumentOutOfRangeException("start", "The start index is out of range"); } if (count < 0 || count > _size - start) { throw new ArgumentOutOfRangeException("count", " The count is out of range"); } SinglyLinkedNode curr = GetNodeAt(start); int res = -1; for (int i = 0; i < count; i++) { if (curr.Item.Equals(item)) { res = i; } curr = curr.Next; } if (res == -1) { return(res); } return(res + start); }
//Return the index of the first occurrence of the given item beginning the search at index start, searching through a length of count. O(n) public int IndexOf(Object item, int start, int count) { if (start < 0 || start >= _size) { throw new ArgumentOutOfRangeException("start", "The start index is out of range"); } if (count < 0 || start > _size - count) { throw new ArgumentOutOfRangeException("count", "The count is out of range"); } SinglyLinkedNode curr = GetNodeAt(start); int res = start; while (res < count + start) { if (curr.Item.Equals(item)) { return(res); } curr = curr.Next; res++; } return(-1); }
//Remove the items trough the specified range. O(n) public void RemoveSection(int start, int count) { if (start < 0 || start >= _size) { throw new ArgumentOutOfRangeException("start", "The start index is out of range"); } if (count < 0 || count > _size - start) { throw new ArgumentOutOfRangeException("count", "The count is out of range"); } if (start == 0 && count == _size) { _head = null; _size = 0; return; } if (start == 0) //Base case remove from front { SinglyLinkedNode newHead = GetNodeAt(count); _head = newHead; } else { SinglyLinkedNode prev = GetNodeAt(start - 1); SinglyLinkedNode next = GetNodeAtFrom(start + count, prev, start - 1); prev.Next = next; } _size -= count; }
/// <summary> /// Removes the element at the specified index of the <see cref="SinglyLinkedList<T>"/>. /// </summary> /// <param name="index">The zero-based index of the element to remove.</param> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when /// <paramref name="index"/> is less than zero or <paramref name="index"/> is /// greater than or equal to <see cref="SinglyLinkedList<T>"/>.Count.</exception> public void RemoveAt(int index) { if (index < 0 || index >= this.size) { throw new ArgumentOutOfRangeException( "index", "Index was out of range. Must be non-negative and less than the size of the collection."); } if (index == 0) { this.RemoveBeginning(); return; } // find the item at the specified index int currentIndex = 0; SinglyLinkedNode <T> currentNode = this.firstNode; while (currentIndex < index - 1) { currentNode = currentNode.NextNode; currentIndex++; } this.RemoveAfter(currentNode); }
public void Sample() { IStack <SinglyLinkedNode <String> > stack = new LinkedStack <String>(); Int32 cycleNumber = 10; Int32 popNumber = cycleNumber / 2; SinglyLinkedNode <String> tmpSequentialNode = null; for (Int32 i = 0; i < cycleNumber; i++) { stack.Push(new SinglyLinkedNode <String>() { Data = i.ToString() }); if (i >= popNumber) { stack.Pop(); } else { tmpSequentialNode = stack.Get(); Console.WriteLine($"SinglyLinkedNode data is 【{tmpSequentialNode.Data}】"); } } Console.WriteLine($"【{MethodBase.GetCurrentMethod().DeclaringType.FullName}】 end."); }
//Remove the item from the set if it is present. O(n) public void Remove(Object item) { SinglyLinkedNode curr = _head; if (curr.Item.Equals(item)) { _head = _head.Next; _size--; return; } SinglyLinkedNode prev = curr; curr = curr.Next; while (curr != null) { if (curr.Item.Equals(item)) { prev.Next = curr.Next; _size--; break; } prev = curr; curr = curr.Next; } }
/// <summary> /// Inserts an element into the <see cref="SinglyLinkedList<T>"/> at the specified index. /// </summary> /// <param name="index">The zero-based index at which item should be inserted.</param> /// <param name="item">The object to insert. The value can be null for reference types.</param> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when /// <paramref name="index"/> is less than zero or <paramref name="index"/> is /// greater than or equal to <see cref="SinglyLinkedList<T>"/>.Count.</exception> public void Insert(int index, T item) { if (index < 0 || index > this.size) { throw new ArgumentOutOfRangeException( "index", "Index was out of range. Must be non-negative and less than or equal to the size of the collection."); } SinglyLinkedNode <T> newNode = new SinglyLinkedNode <T>(item); if (index == 0) { this.InsertBeginning(newNode); return; } // find the item at the specified index int currentIndex = 0; SinglyLinkedNode <T> currentNode = this.firstNode; while (currentIndex < index - 1) { currentNode = currentNode.NextNode; currentIndex++; } this.InsertAfter(currentNode, newNode); }
//get next item in a LIFO manner public T Pop() { //empty list condition if (this.Head == null && this.Tail == null) { throw new InvalidOperationException(); //if we have an empty list then throw an invalid operation exception } //single item in list condition else if (this.Head == this.Tail) { SinglyLinkedNode <T> nxt = this.Head; //make a reference to the top value of the stack this.Head = this.Tail = null; //because we only have 1 value in the list, both head and tail will reset to null this._Count--; return(nxt.Data); //return the value in nxt } //otherwise fetch to head else { SinglyLinkedNode <T> nxt = this.Head; //make reference of the top value this.Head = this.Head.Next; //move head to the next value nxt.Next = null; //because nxt is a reference to the old head, we can set the next value to null will cause the garbage collector to pick it up this._Count--; return(nxt.Data); //return the value } }
/// <summary>Attempts to remove an item from the start of the queue.</summary> /// <param name="item">The item dequeued if successful.</param> /// <returns>True if the operation succeeds, false if the queue was empty.</returns> public bool TryDequeue(out T item) { for (;;) { SinglyLinkedNode <T> curHead = _head; SinglyLinkedNode <T> curTail = _tail; SinglyLinkedNode <T> curHeadNext = curHead.Next; if (curHead == curTail) { if (curHeadNext == null) { item = default(T); return(false); } else { Interlocked.CompareExchange(ref _tail, curHeadNext, curTail); // assist obstructing thread } } if (Interlocked.CompareExchange(ref _head, curHeadNext, curHead) == curHead) { item = curHeadNext.Item; return(true); } } }
public SinglyLinkedNode <T> RemoveDuplicates <T>(SinglyLinkedNode <T> headOfList) { if (headOfList == null) { throw new ArgumentNullException(nameof(headOfList)); } var dict = new Dictionary <T, int>(); var prev = headOfList; var current = headOfList.Next; dict.Add(prev.Data, 1); while (current != null) { if (dict.ContainsKey(current.Data)) { prev.Next = current.Next; //removing node } else { dict.Add(current.Data, 1); prev = current; } current = current.Next; } return(headOfList); }
public SinglyLinkedListImplementation <T> Merge <T>(SinglyLinkedNode <T> headOfFirstList, SinglyLinkedNode <T> headOfSecondList) where T : IComparable <T> { var resultList = new SinglyLinkedListImplementation <T>(); var firstPointer = headOfFirstList; var secondPointer = headOfSecondList; while (firstPointer != null && secondPointer != null) { if (firstPointer.Data.CompareTo(secondPointer.Data) < 0) { resultList.AddAtEnd(firstPointer.Data); firstPointer = firstPointer.Next; } else { resultList.AddAtEnd(secondPointer.Data); secondPointer = secondPointer.Next; } } while (firstPointer != null) { resultList.AddAtEnd(firstPointer.Data); firstPointer = firstPointer.Next; } while (secondPointer != null) { resultList.AddAtEnd(secondPointer.Data); secondPointer = secondPointer.Next; } return(resultList); }
/// <summary>Pushes a collection of items to the top of the stack as a single atomic operation.</summary> /// <param name="collection">The items to push onto the stack.</param> /// <exception cref="ArgumentNullException">The collection was null.</exception> public void PushRange(IEnumerable <T> collection) { Validation.NullCheck(collection, "collection"); using (IEnumerator <T> en = collection.GetEnumerator()) { if (!en.MoveNext()) { return; } var start = new SinglyLinkedNode <T>(en.Current); var end = start; while (en.MoveNext()) { var newNode = new SinglyLinkedNode <T>(en.Current); end.Next = newNode; end = newNode; } var next = end.Next = _head.Next; for (;;) { SinglyLinkedNode <T> oldNext = Interlocked.CompareExchange(ref _head.Next, start, next); if (oldNext == next) { return; } next = end.Next = oldNext; } } }
public void ShouldReturn5thElementFromTheEndOfList() { var cut = new FindNodeFromEndOfLinkedList <int>(); SinglyLinkedNode <int> n = new SinglyLinkedNode <int>(1) { Next = new SinglyLinkedNode <int>(2) { Next = new SinglyLinkedNode <int>(8) { Next = new SinglyLinkedNode <int>(3) { Next = new SinglyLinkedNode <int>(7) { Next = new SinglyLinkedNode <int>(0) { Next = new SinglyLinkedNode <int>(4) } } } } } }; Assert.AreEqual(8, cut.Find(n, 5)); }
//get next item in a FIFO public T Dequeue() { //empty list condition if (this.Head == null && this.Tail == null) { throw new InvalidOperationException(); //if we have an empty list then throw an invalid operation exception } //single item in list condition else if (this.Head == this.Tail) { SinglyLinkedNode <T> nxt = this.Tail; //since we only have one value, we could reference either head or tail, to be consistent we will use tail this.Head = this.Tail = null; //because we only have 1 value in the list, both head and tail will reset to null this._Count--; return(nxt.Data); //return the value in nxt } //otherwise fetch to tail else { SinglyLinkedNode <T> nxt = this.Tail; //make reference of the top value SinglyLinkedNode <T> ptr = this.Head; //we need a pointer because we need to get to the value 1 before the tail //because we use a singly linked list, we need to iterate from the top to get the value one before the tail, this is a performance issue we could //rectify by using a doubly linked list, then we could say this.Tail.Prev and make this an O(1) operation instead of O(n) while (ptr.Next != this.Tail) { ptr = ptr.Next; } ptr.Next = null; //unhook our pointer from the tail this.Tail = ptr; //make tail point to the ptr this._Count--; return(nxt.Data); //return our value } }
//Push a new item on top of the stack. O(1) public void Push(Object item) { SinglyLinkedNode newHead = new SinglyLinkedNode(item); newHead.Next = _head; _head = newHead; _size++; }
public T Pop() { var item = _first.Item; _first = _first.Next; Count--; return(item); }
public T Dequeue() { var item = _first.Item; _first = _first.Next; Count--; return(item); }
/// <summary>Moves to the next item.</summary> /// <returns>True if an item is found, false if it reaches the end of the queue.</returns> public bool MoveNext() { if (_node == _tail) { return(false); } _node = _node.Next; return(true); }
/// <summary>Clears the queue as a single atomic operation.</summary> public void Clear() { SinglyLinkedNode <T> head = _head; SinglyLinkedNode <T> oldHead; while ((oldHead = Interlocked.CompareExchange(ref _head, _tail, head)) != head) { head = oldHead; } }
public T Pop() { T ret = _head.Pop(); if (_head.IsEmpty && _head.Next != null) { _head = _head.Next; } return(ret); }
public static void PrintList(SinglyLinkedNode head) { var curNode = head; while (curNode != null) { Console.Write($"{(curNode == head ? "" : "->")}{curNode.Data}"); curNode = curNode.Next; } }
public void CopyTo(T[] array, int arrayIndex) { SinglyLinkedNode <T> ptr = this.Head; for (int i = arrayIndex; i < this._Count; i++) { array[i] = ptr.Data; ptr = ptr.Next; } }
//Reverse the items of the list trough the given range. O(n) public void ReverseSection(int start, int count) { if (start < 0 || start >= _size) { throw new ArgumentOutOfRangeException("start", "The start index is out of range"); } if (count < 0 || count > _size + start) { throw new ArgumentOutOfRangeException("count", "The count is out of range"); } SinglyLinkedNode begSegEnd = null; if (start != 0) { begSegEnd = GetNodeAt(start - 1); } SinglyLinkedNode endSegBeg; if (begSegEnd == null) { endSegBeg = GetNodeAt(count); } else { endSegBeg = GetNodeAtFrom(start + count, begSegEnd, start - 1); } SinglyLinkedNode curr = _head; if (begSegEnd != null) { curr = begSegEnd.Next; } for (int i = 0; i < count; i++) { SinglyLinkedNode nextCurr = curr.Next; curr.Next = endSegBeg; endSegBeg = curr; curr = nextCurr; } if (begSegEnd == null) { _head = endSegBeg; return; } begSegEnd.Next = endSegBeg; }
internal AtDequeuEnumerable(SlimConcurrentQueue <T> queue) { SinglyLinkedNode <T> head; SinglyLinkedNode <T> tail; while (Interlocked.CompareExchange(ref queue._head, tail = queue._tail, head = queue._head) != head) { } _start = head; _end = tail; }
/// <summary>Moves to the next item.</summary> /// <returns>True if an item is found, false if it reaches the end of the stack.</returns> public bool MoveNext() { SinglyLinkedNode <T> next = _node.Next; if (next == null) { return(false); } _node = next; return(true); }
public IEnumerator <SinglyLinkedNode <T> > GetEnumerator() { SinglyLinkedNode <T> currentNode = this; do { SinglyLinkedNode <T> returnNode = currentNode; currentNode = currentNode.NextNode; yield return(returnNode); }while (currentNode != null); }
public void Push(T item) { var currentFirst = _first; _first = new SinglyLinkedNode <T> { Next = currentFirst, Item = item }; Count++; }
/// <summary>Attempts to obtain a the item at the start of the queue without removing it.</summary> /// <param name="item">The item found.</param> /// <returns>True if the method succeeds, false if the queue was empty.</returns> public bool TryPeek(out T item) { SinglyLinkedNode <T> node = _head.Next; if (node == null) { item = default(T); return(false); } item = node.Item; return(true); }
public SinglyLinkedNode Push(T item) { if (_size == ArraySize - 1) { SinglyLinkedNode n = new SinglyLinkedNode(); n.Next = this; n.Push(item); return(n); } _array[_size++] = item; return(this); }
public void Delete() { var list = new SinglyLinkedList <int>(); Assert.AreEqual(0, list.Count()); /* Deleting an item from an empty list. */ Assert.IsFalse(list.Delete(10)); /* Deleting a non-existing item from a list with one element. */ list.Insert(5); Assert.AreEqual(1, list.Count()); Assert.IsFalse(list.Delete(10)); Assert.AreEqual(1, list.Count()); Assert.AreEqual(5, list.Head().Value); /* Deleting the only node from the list (aka. Head).*/ Assert.AreEqual(1, list.Count()); Assert.IsTrue(list.Delete(5)); Assert.AreEqual(0, list.Count()); Assert.IsNull(list.Head()); /*Deleting a non-existing item from a list with 2 items. */ var head = new SinglyLinkedNode <int>(5) { Next = new SinglyLinkedNode <int>(10) }; list = new SinglyLinkedList <int>(head); Assert.AreEqual(2, list.Count()); Assert.IsFalse(list.Delete(16)); Assert.AreEqual(2, list.Count()); /*Deleting an existing item from a list with 2 items*/ Assert.AreEqual(2, list.Count()); Assert.IsTrue(list.Delete(5)); Assert.AreEqual(1, list.Count()); Assert.AreEqual(10, list.Head().Value); Assert.IsNull(list.Head().Next); /* Deleting head from a list with 3 nodes.*/ head = new SinglyLinkedNode <int>(10) { Next = new SinglyLinkedNode <int>(3) }; head.Next.Next = new SinglyLinkedNode <int>(1); list = new SinglyLinkedList <int>(head); Assert.AreEqual(3, list.Count()); Assert.IsTrue(list.Delete(10)); Assert.AreEqual(2, list.Count()); Assert.AreEqual(3, list.Head().Value); }