Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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")
Example #5
0
    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)
Example #6
0
    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
Example #7
0
    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