/// <summary> /// Prints the contents of a list in reverse /// </summary> /// <remarks> /// This approach uses a stack to push and pop off the values. /// </remarks> /// <param name="node"></param> public static void RunIterativelyReverse(LinkListNode node) { Stack<LinkListNode> stack = new Stack<LinkListNode>(); // Step #1 - push all the elements into a stack for (LinkListNode n = node; n != null; n = n.next) { stack.Push(n); // PUSH } Console.Write("(null)"); // Step #2 - pop each element off and print while (stack.Count != 0) { stack.Pop().PrintNode(false, false); // POP if (node.prev != null) { Console.Write("<->"); } else { if (stack.Count > 0) { Console.Write("<-"); } } } }
/// <summary> /// Determines if linked list contains a loop /// Method: Use two pointers to traverse the list, one slow (increments by 1) and one fast (increments by 2) /// If the faster pointer reaches null, the linked list does not contain a loop. /// If the slower pointer is ahead of the faster pointer or equal to it, then a loop is present. /// Performance: Leading pointer ends at n nodes, trailing pointer would have reached n/2 /// 3/2n = O(n) 1 1/2 nodes examined /// </summary> /// <param name="head"></param> /// <returns></returns> public static bool Run( LinkListNode head) { if (head == null) { throw new System.ArgumentNullException("FindLoopInList error, arguement head cannot be null."); } LinkListNode leadingPtr; LinkListNode trailingPtr; trailingPtr = head; leadingPtr = trailingPtr.next; if (leadingPtr == null) return false; while (leadingPtr != null && trailingPtr != null) { if (trailingPtr == leadingPtr) { return true; } trailingPtr = trailingPtr.next; leadingPtr = leadingPtr.next; if (leadingPtr != null) { leadingPtr = leadingPtr.next; } else { return false; } } return false; }
/// <summary> /// Finds the nth to last element in a linked list /// </summary> /// <remarks> /// This approach uses a leading and trailing pointer to step through the link list /// The leading pointer is sent out first and a counter is kept. /// Once the counter reaches the nth mark, the trailing pointer is advanced /// When the leading pointer reaches null, the trailing pointer will be pointing at the nth element. /// /// </remarks> /// <returns></returns> public static int RunIterative(LinkListNode head, int nth) { LinkListNode leadingPtr; LinkListNode trailingPtr; if (head == null) { throw new System.ArgumentNullException("FindNthToLast, head must be a non null value."); } leadingPtr = head; for (int i=0; i<nth; i++) { leadingPtr = leadingPtr.next; if (leadingPtr == null) { throw new System.ArgumentOutOfRangeException("FindNthToLast, nth is out of range"); } } trailingPtr = head; while (leadingPtr.next != null) { trailingPtr = trailingPtr.next; leadingPtr = leadingPtr.next; } return trailingPtr.key; }
/// <summary> /// Adds the values of all the nodes in a linked list using recusion /// </summary> /// <remarks> /// Recursion terminates when we reach null. /// Add the node value to the return value and call next node. /// </remarks> /// <param name="head"></param> /// <returns></returns> public static int RunRecusively(LinkListNode head) { if (head == null) { return 0; } else { return head.key + RunRecusively(head.next); } }
/// <summary> /// Finds the length of a linked list recursively /// </summary> /// <remarks> /// Recursive operation terminates when we reach null node. /// We add one to the returned value and pass in next node. /// </remarks> /// <returns></returns> public static int RunRecursively(LinkListNode head) { if (head == null) // terminate logic when we reach end of linked list { return 0; } else { return 1 + RunRecursively(head.next); // simply add 1 and call until we reach end of list } }
/// <summary> /// Finds the nth to last element in a linked list /// </summary> /// <param name="head"></param> /// <param name="nth"></param> /// <returns></returns> public static void RunRecursion(LinkListNode head, int nth) { if (head == null) { return; } RunRecursion(head.next, nth); if (i++ == nth) { Console.WriteLine(nth.ToString() + " to last element in linked list: " + head.key); } }
/// <summary> /// Reverses a linked list /// </summary> /// <remarks> /// /// Steps: /// If we reach null, pass back node (recursive termination condition) /// Get next node, by recusively calling function and passing node's next /// Switch pointer, point heads.next's next pointer back at head /// Break head's next link, set next to null /// return the node /// /// </remarks> /// <param name="head"></param> /// <returns></returns> public static LinkListNode RunRecursively(LinkListNode head) { LinkListNode node; if (head.next == null) { return head; // recursive termination condition } node = RunRecursively(head.next); // dive down into the linked list head.next.next = head; // point head's next node's next pointer back at head head.next = null; // break link from head to next node return node; // return node }
/// <summary> /// Removes a node from a linked list /// </summary> /// <remarks> /// Note this approach only works when removing nodes other than head /// </remarks> /// <param name="node"></param> /// <param name="key"></param> /// <returns></returns> public static LinkListNode RunRecursively(LinkListNode node, int key) { if (node != null) { if (node.key == key) { node = node.next; // advance the pointer } else { node.next = RunRecursively(node.next, key); } } return node; }
/// <summary> /// Reverses a linked list /// </summary> /// <remarks> /// This uses an iterative approach using a current, previous and next pointer. /// /// Steps: /// Get handle to next node, assign next to point to next node /// Break link to next node, assign current's next to previous /// No longer need previous, reassign previous to current /// Advance current to next /// Repeat until current is null /// </remarks> /// <param name="head"></param> /// <returns></returns> public static void RunIteratively(ref LinkListNode head) { LinkListNode current = head; LinkListNode previous = null; LinkListNode next = null; while (current != null) { next = current.next; // step the next pointer by one current.next = previous; // reassign current node to point to previous previous = current; // advance previous to the current node current = next; // increment current to the next node } head = previous; }
/// <summary> /// Creates a copy of a linked list /// </summary> /// <remarks> /// Uses a rescursive approach to copy each element of a linked list /// </remarks> /// <param name="head"></param> /// <returns></returns> public static LinkListNode RunRecursively(LinkListNode head) { LinkListNode node; if (head == null) { return null; } else { node = new LinkListNode(); node.key = head.key; node.next = RunRecursively(head.next); return node; } }
/// <summary> /// Removes a node from a ordered linked list /// </summary> /// <param name="head"></param> /// <param name="key"></param> /// <param name="isDoublyLinked"></param> public static void Run(ref LinkListNode head, int key, bool isDoublyLinked) { LinkListNode node; LinkListNode prev; if (head == null) { throw new System.ArgumentNullException("RemoveNode Error, head cannont be a null value."); } //Check #1 - Check if we are removing head if (head.key == key) { node = head; head = head.next; if (isDoublyLinked == true && head != null) { head.prev = null; } node = null; } else { node = null; prev = head; while (prev.next != null && prev.next.key != key) { prev = prev.next; } if (prev.next != null && prev.next.key == key) { node = prev.next; prev.next = node.next; if (isDoublyLinked == true && node.next != null) { node.next.prev = node; } node = null; } else { Console.WriteLine("RemoveNode Warning - value " + key + " was not found in linked list."); } } }
/// <summary> /// Creates a singly linked list /// </summary> /// <param name="values"></param> /// <param name="head"></param> public static void CreateSinglyLinked(int[] values, out LinkListNode head) { LinkListNode node = null; if (values == null || values.Length == 0) { throw new System.ArgumentException("CreateList error, values must contain at least one value."); } head = new LinkListNode(); head.key = values[0]; node = head; for (int i = 1; i < values.Length; i++) { node.next = new LinkListNode(); // assign the next pointer of current node node = node.next; // advance pointer to newly created node node.key = values[i]; // assign value to new node from passed in arguments } }
/// <summary> /// Finds the length of a linked list iteratively /// </summary> /// <returns></returns> public static int RunIteratively(LinkListNode head) { LinkListNode node; int i; if (head == null) { return 0; } node = head; i = 1; while (node.next != null) { node = node.next; i++; } node = null; return i; }
/// <summary> /// Iteratively adds the node values in a linked list /// </summary> /// <param name="head"></param> /// <returns></returns> public static int RunIteratively(LinkListNode head) { LinkListNode node; int sum; if (head == null) { return 0; } node = head; sum = head.key; while (node.next != null) { node = node.next; sum += node.key; } node = null; return sum; }
/// <summary> /// Prints the contents of a linked list /// </summary> /// <param name="head"></param> public static void RunIteratively(LinkListNode head) { LinkListNode node; if (head == null) { throw new System.ArgumentNullException("PrintList error, head arguement null."); } node = head; // check for loop if (FindLoopInList.Run(head) == true) { Console.WriteLine("PrintList Warning, list contains loop, unable to print."); return; } while (node != null) { node.PrintNode(false, false); if (node.prev != null && node.next != null) { Console.Write("<->"); } else { Console.Write("->"); } node = node.next; if (node == null) { Console.Write("(null)\n"); } } }
/// <summary> /// Prints the contents of a linked list /// </summary> /// <remarks> /// Recursively traverses the linked list and prints out node values /// </remarks> /// <param name="node"></param> public static void RunRecursively(LinkListNode node) { if (node == null) { Console.Write("(null)\n"); return; } else { node.PrintNode(false, false); if (node.prev != null && node.next != null) { Console.Write("<->"); } else { Console.Write("->"); } RunRecursively(node.next); } }
/// <summary> /// Prints the contents of a linked list in reverse /// </summary> /// <param name="node"></param> public static void RunRecursivelyReverse(LinkListNode node) { if (node == null) { Console.Write("(null)"); // <- Note the order, very important!!! return; } else { RunRecursivelyReverse(node.next); // <- Note the order, very important!!! if (node.next != null) // we check for "next" instead of "prev" { Console.Write("<->"); } else { Console.Write("<-"); // we write arrow before writting number } node.PrintNode(false, false); } }
/// <summary> /// Finds the location to insert the node /// </summary> /// <param name="head"></param> /// <param name="key"></param> /// <returns></returns> private static LinkListNode FindPosition(LinkListNode head, int key) { LinkListNode prev = null; if (head.key > key) { return null; // return null; } else { prev = head; while (prev.next != null && key > prev.next.key) { prev = prev.next; } } return prev; }
/// <summary> /// Inserts value into linked list /// </summary> /// <param name="head"></param> /// <param name="key"></param> /// <param name="isDoublyLinked"></param> public static void Run( LinkListNode head, int key, bool isDoublyLinked = false) { LinkListNode node; LinkListNode prev; node = new LinkListNode(); node.key = key; // Check #1 - Insert as new head if no head exists if (head == null) { node.next = null; node.prev = null; head = node; return; } // Check #2 - Insert as new head if (head.key > key) { // Option 1, use "ref" keyword and change what head points to. node.prev = null; node.next = head; if (isDoublyLinked == true) { head.prev = node; } head = node; /* // Option 2, insert new node after head and swap head and new node's key, retaining heads reference node.next = head.next; head.next = node; node.key = head.key; head.key = key; if (isDoublyLinked == true) { if(node.next != null) { node.next.prev = node; } node.prev = head; } **/ } else { prev = head; while (prev.next != null && key > prev.next.key) { prev = prev.next; } node.next = prev.next; prev.next = node; if (isDoublyLinked == true) { if (node.next != null) { node.next.prev = node; } node.prev = head; } } }