Example #1
0
    def delete_at_beginning(self):
        if self.head is None:
            raise EmptyListError("List is empty, can't delete.")

        temp = self.head
        self.head = temp.get_next()
        temp.set_next(None)
Example #2
0
    def insert_at_position(self, position, data):
        """ Position is 1 based. """
        if self.head is None:
            raise EmptyListError("List is empty, can't insert.")

        list_length = self.get_length()
        if not (1 <= position <= list_length + 1):
            raise RangeError(
                "Position range must be 1 through {0}.".format(list_length +
                                                               1))

        if position == 1:
            self.insert_at_beginning(data)
        elif position == list_length + 1:
            self.insert_at_end(data)
        else:
            pointer = self.head
            pos = 1
            while pos != position - 1:
                pointer = pointer.get_next()
                pos += 1

            node = NodeCircular(data)
            node.set_next(pointer.get_next())
            pointer.set_next(node)
Example #3
0
def find_middle_of_the_list(linked_list):
    """
    Find the middle node of a single linked list.

    :param SingleLinkedList linked_list: The linked list to operate.
    :return: data for middle node of the list.
    :rtype: int
    :raises EmptyListError: if the list is empty.
    """
    if linked_list.head is None:
        raise EmptyListError("List is empty, cannot find middle")

    pointer1 = linked_list.head
    pointer2 = linked_list.head
    count = 0

    # Move one pointer at one step, second pointer at two steps.
    # The pointer which traversed at one step a time would point to
    # middle node at the end of the iteration.
    while pointer1.get_next():
        if count == 0:
            pointer1 = pointer1.get_next()
            count = 1

        elif count == 1:
            pointer1 = pointer1.get_next()
            pointer2 = pointer2.get_next()
            count = 0

    return pointer2.data
Example #4
0
def nth_node_from_end(linked_list, n):
    """
    Find nth node from end of a linked list (assume positions as 1 based).
    Hint: For a linked list of size m, nth node from end would be
    (m - n + 1)th node from beginning.

    :param SingleLinkedList linked_list: The linked list to operate.
    :param int n: The position from end.
    :return: the data of the node.
    :rtype: int
    :raises EmptyListError: if the list is empty.
    :raises RangeError: if length of list < n < 0.
    """

    list_length = linked_list.get_length()
    if list_length == 0:
        raise EmptyListError("List is empty, can't find node")

    if not (1 <= n <= list_length):
        raise RangeError("Position range must be 1 through {0}".format(list_length))

    nth_from_end = list_length - n + 1
    pointer = linked_list.head
    position = 1

    while position != nth_from_end:
        pointer = pointer.get_next()
        position += 1

    return pointer.data
Example #5
0
def insert_into_sorted_list(linked_list, data):
    """
    Insert a node in a sorted linked list at its proper position.

    :param SingleLinkedList linked_list: The linked list to operate.
    :return: nothing.
    :rtype: None
    :raises EmptyListError: if the list is empty.
    """
    if linked_list.head is None:
        raise EmptyListError("List is empty, cannot insert")

    position = 1
    pointer = linked_list.head
    insert_at_end = True
    while pointer:
        if pointer.data >= data:
            linked_list.insert_at_position(position, data)
            insert_at_end = False
            break
        pointer = pointer.get_next()
        position += 1

    if insert_at_end:
        linked_list.insert_at_end(data)
Example #6
0
    def delete_at_end(self):
        if self.head is None:
            raise EmptyListError("List is empty, can't delete.")

        list_length = self.get_length()
        if list_length == 1:
            self.delete_at_beginning()
        else:
            pointer = self.head
            while pointer.get_next():
                pointer = pointer.get_next()

            pointer.get_previous().set_next(None)
Example #7
0
    def delete_at_beginning(self):
        if self.head is None:
            raise EmptyListError("List is empty, can't delete.")

        if self.get_length() == 1:
            self.head = None
        else:
            pointer = self.head
            while pointer:
                if pointer.get_next() == self.head:
                    break
                pointer = pointer.get_next()

            temp = self.head
            self.head = temp.get_next()
            temp.set_next(None)
            pointer.set_next(self.head)
Example #8
0
def intersecting_node(list1, list2):
    """
    Suppose there are two linked lists of lengths l1 and l2,
    both of which intersect at some point and become a single linked list.
    The head of both linked lists are known. The intersecting node of the
    lists is not known. The number of nodes in each list before intersecting
    and the lengths of the lists are also unknown. Find the intersecting node.

    :param SingleLinkedList list1: The first linked linked.
    :param SingleLinkedList list2: The second linked list.
    :return: the data of the intersecting node.
    :rtype: int
    :raises EmptyListError: if the list is empty.
    """

    if list1 is None or list2 is None:
        raise EmptyListError(
            "List(s) is/are empty, can't find intersecting node")

    l1 = list1.get_length()
    l2 = list2.get_length()

    pointer1 = list1.head
    pointer2 = list2.head

    d = l1 - l2
    if l1 < l2:
        d = l2 - l1
        pointer1 = list2.head
        pointer2 = list1.head

    for i in range(d):
        pointer1 = pointer1.get_next()

    while pointer1 and pointer2:
        if pointer1 == pointer2:
            return pointer2.data

        pointer1 = pointer1.get_next()
        pointer2 = pointer2.get_next()

    return None
Example #9
0
    def delete_at_position(self, position):
        """ Position is 1 based. """
        if self.head is None:
            raise EmptyListError("List is empty, can't delete.")

        list_length = self.get_length()
        if not (1 <= position <= list_length):
            raise RangeError(
                "Position range must be 1 through {0}.".format(list_length))

        if position == 1:
            self.delete_at_beginning()
        else:
            pointer = self.head
            pos = 1
            while pos != position - 1:
                pointer = pointer.get_next()
                pos += 1

            next = pointer.get_next().get_next()
            pointer.get_next().set_next(None)
            pointer.set_next(next)
def reverse_single_linked_list(linked_list):
    """
    Reverse a given single linked list.

    :param SingleLinkedList linked_list: The linked list to operate.
    :return: nothing.
    :rtype: None
    :raises EmptyListError: if the list is empty.
    """
    if linked_list.head is None:
        raise EmptyListError("List is empty, cannot reverse")

    previous = None
    pointer = linked_list.head

    while pointer:
        next = pointer.get_next()
        pointer.set_next(previous)
        previous = pointer
        pointer = next

    linked_list.head = previous
def loop_in_a_list(linked_list):
    """
    Check whether a given linked list ends in a cycle (cyclic). If yes,
    find the start node of the loop.

    :param SingleLinkedList linked_list: The linked list to operate.
    :return: whether cyclic, and also start node if it is cyclic.
    :rtype: tuple
    :raises EmptyListError: if the list is empty.
    """
    if linked_list.head is None:
        raise EmptyListError("List is empty, cannot continue operation")

    is_cyclic = False
    slow_ptr = linked_list.head
    fast_ptr = linked_list.head

    # fast_ptr traverses two steps at a time, slow_ptr traverses one step at
    # a time. If they meet at a point, there is a loop in the list.
    while slow_ptr and fast_ptr and fast_ptr.get_next():
        slow_ptr = slow_ptr.get_next()
        fast_ptr = fast_ptr.get_next().get_next()
        if fast_ptr == slow_ptr:
            is_cyclic = True
            break

    if is_cyclic:
        # Set slow_ptr to head node
        slow_ptr = linked_list.head

        # Now, traverse both pointers one step a time, the point where they meet
        # is the beginning of the loop.
        while slow_ptr != fast_ptr:
            fast_ptr = fast_ptr.get_next()
            slow_ptr = slow_ptr.get_next()

    return is_cyclic, fast_ptr and fast_ptr.data
Example #12
0
    def delete_at_end(self):
        if self.head is None:
            raise EmptyListError("List is empty, can't delete.")

        list_length = self.get_length()
        if list_length == 1:
            self.delete_at_beginning()
        else:
            # Keep track of 2 pointers, one is the traversing and
            # the other one is the node previous to it. The `previous`
            # moves 1 step ahead after `pointer` has moved 2 steps.
            pointer = self.head
            previous = self.head
            steps = 1

            while pointer.get_next():
                pointer = pointer.get_next()
                if steps == 2:
                    previous = previous.get_next()
                    steps = 1

                steps += 1

            previous.set_next(None)
def lenth_of_the_loop(linked_list):
    """
    Find the length of the loop in a linked list if it exists.

    :param SingleLinkedList linked_list: The linked list to operate.
    :return: the count of number of nodes in the loop.
    :rtype: int
    :raises EmptyListError: if the list is empty.
    """
    if linked_list.head is None:
        raise EmptyListError("List is empty, cannot continue operation")

    is_cyclic = False
    slow_ptr = linked_list.head
    fast_ptr = linked_list.head

    # fast_ptr traverses two steps at a time, slow_ptr traverses one step at
    # a time. If they meet at a point, there is a loop in the list.
    while slow_ptr and fast_ptr and fast_ptr.get_next():
        slow_ptr = slow_ptr.get_next()
        fast_ptr = fast_ptr.get_next().get_next()
        if fast_ptr == slow_ptr:
            is_cyclic = True
            break

    counter = 0
    if is_cyclic:
        # At this point, fast_ptr == slow_ptr.
        # Keep moving the fast_ptr till it comes back again to slow_ptr,
        # increasing the counter at each iteration.
        counter += 1
        while slow_ptr != fast_ptr.get_next():
            fast_ptr = fast_ptr.get_next()
            counter += 1

    return counter