def partition(self, value): """Partition linked list separated by node with value Solution: Separate values into two singly linked list, one with elements less than value and the other with elements greater than or equal to value. Then join linked lists together. \param value Pivot node value """ # Empty condition if self.is_empty(): raise Empty("List is empty") # Verify pivot value exists, or else return None pivot = self._head while pivot is not None: if pivot._data == value: break pivot = pivot._next if pivot is None: return # Create pointers to two linked lists ptr1 = ptr2 = None curr = self._head self._head = None while curr is not None: tmp = curr curr = curr._next tmp._next = None # Left partition if tmp._data < value: if ptr1 is None: ptr1 = ptr1_curr = tmp else: ptr1_curr._next = tmp ptr1_curr = ptr1_curr._next # Right partition else: if ptr2 is None: ptr2 = ptr2_curr = tmp else: ptr2_curr._next = tmp ptr2_curr = ptr2_curr._next # Join linked lists together if ptr1 is not None: self._head = ptr1 ptr1_curr._next = ptr2 else: self._head = ptr2 if ptr2 is not None: self._tail = ptr2_curr else: self._tail = ptr1_curr
def remove_dups_iterative(self): """Iteratively remove duplicates from the linked list""" if self.is_empty(): raise Empty("List is empty") curr = self._head while curr is not None: ptr1 = curr ptr2 = ptr1._next while ptr2 is not None: if ptr2._data == curr._data: ptr1._next = ptr2._next is_tail = False if ptr2 is self._tail: is_tail = True ptr2 = ptr1 if is_tail: self._tail = ptr2 self._size -= 1 else: ptr1 = ptr1._next ptr2 = ptr2._next curr = curr._next
def dequeueAny(self): """Dequeue oldest element in the linked list :returns Oldest animal in the list """ if self._list.head is None: raise Empty("List is empty") e = self._list.head.data self._list.head = self._list.head.next return e
def dequeueCat(self): """Dequeues oldest cat in the linked list :returns Oldest cat in the list """ if self._list.head is None: raise Empty("List is empty") curr = self._list.head if isinstance(curr.data, Cat): e = self._list.head.data self._list.head = self._list.head.next return e while curr.next is not None: if isinstance(curr.next.data, Cat): e = curr.next.data curr.next = curr.next.next return e curr = curr.next raise Empty("No cats in queue")
def is_palindrome(self): """Determine if linked list is a palindrome :returns Boolean if linked list is a palindrome """ if self.is_empty(): raise Empty("List is empty") elif len(self) == 1: return True def is_palindrome_helper(node_end): """Helper function to check if list is a palindrome :param node_end node at end of the list :returns True if linked list is a palindrome""" if node_end is None: return self._head node_begin = is_palindrome_helper(node_end._next) if node_begin is True: return True elif node_begin is False: return False elif node_begin._data != node_end._data: return False else: if node_begin is node_end: return True if node_begin._next is node_end: return True else: return node_begin._next return is_palindrome_helper(self._head)
def kth_to_last_r(self, k): """Recursive solution to return the kth to last node """ self.kth_node = None if self.is_empty(): raise Empty("List is empty") elif k < 1: raise ValueError("Index must > 0") def kth_to_last_helper(node, k): if node is None: return 1 n = kth_to_last_helper(node._next, k) if k > n: return 1 + n elif k == n and self.kth_node is None: self.kth_node = node._data return n kth_to_last_helper(self._head, k) return self.kth_node
def kth_to_last(self, k): """Iterative solution to return the kth to last node in the linked list""" #Do nothing if self.is_empty(): raise Empty("List is empty") if k < 1: raise ValueError("Index must be > 0") #Runner technique slow = fast = self._head while fast._next is not None and k > 1: fast = fast._next k -= 1 #Not enough elements if k > 1: return None #Traverse to the end of the linked list while fast._next is not None: fast = fast._next slow = slow._next return slow._data