Circular Linked List

A circular linked list is a simple linear data structure where objects are linked using pointers to their associated location. Unlike arrays whose objects are stored at continuous locations. Each node stores a reference to an object that is an element of the sequence, as well as a reference to the next node of the circular linked list.

The first node of a circular linked list is known as the head of the linked list. And the last node is known as the tail. The tail of a circular linked list always points to the head.

../../_images/circular_linked_list.gif

⏱ Time-Complexity

The following table sums up all the different public functionality in this class and also provides the worst-case time complexity along side with the optimal time complexity that I will try to reach in future releases Insha’Allah. Generally, we are going to use the following indicators in the table:

  • n is the number of elements currently in the circular linked list.
  • m is the number of elements in the other circular linked list.
  • k is the value of a given index.
Method Description Worst-case Optimal
is_empty() Checks if the circular linked list is empty. O(1) O(1)
__len__() Returns the nodes count in the circular linked list. O(1) O(1)
__repr__() Represents the circular linked list as a string. O(n) O(n)
__iter__() Iterates over the circular linked list. O(n) O(n)
__eq__() Checks the items equality of two circular linked lists. O(min(n;m)) O(min(n;m))
__ne__() Checks the items inequality of two circular lists. O(min(n;m)) O(min(n;m))
__lt__() Checks if the circular linked list is < the other. O(min(n;m)) O(min(n;m))
__le__() Checks if the circular linked list is <= the other. O(min(n;m)) O(min(n;m))
__gt__() Checks if the circular linked list is > the other. O(min(n;m)) O(min(n;m))
__ge__() Checks if the circular linked list is >= the other. O(min(n;m)) O(min(n;m))
__contains__() Checks the existence of the given item in the list. O(n) O(n)
__getitem__() Returns the element at the given index. O(k%n) O(k%n)
add_front() Adds the given item at the head of the circular list. O(1) O(1)
add_end() Adds the given item at the tail of the circular list. O(n) O(n)
insert() Adds the given item at the given index. O(k%n) O(k%n)
__setitem__() Replaces the value at the given index with given value. O(k%n) O(k%n)
__delitem__() Deletes the value at the given index. O(k%n) O(k%n)
remove_front() Removes the node at the head of the circular list. O(1) O(1)
remove_end() Removes the node at the tail of the circular list. O(n) O(n)
remove() Removes a given value from the circular list if found. O(n) O(n)
clear() Clears the whole circular linked list. O(1) O(1)
split() Splits the circular list into two at the given index. O(k%n) O(k%n)
extend() Extends the circular linked list using another one. O(n+m) O(n+m)
rotate_left() Left-rotates the circular list by the given value. O(k%n) O(k%n)
rotate_right() Right-rotates the circular list by the given value. O(k%n) O(k%n)
reverse() Reverses the circular linked list. O(n) O(n)
to_list() Converts the circular linked list to a normal list. O(n) O(n)
count() Counts the occurrences of the given value in the list. O(n) O(n)
copy() Shallow-copies the circular linked list. O(n) O(n)

☕️ API

Here are all of the public methods that can be used with CircularLinkedList() objects:

class extra.lists.circular_linked_list.CircularLinkedList(iterable=None)

A circular linked list is a simple linear data structure where objects are linked using pointers to their associated location. Unlike arrays whose objects are stored at continuous locations. Each node stores a reference to an object that is an element of the sequence, as well as a reference to the next node of the circular linked list.

__contains__(value)

Checks if the given value exists in the CircularLinkedList() instance in time-complexity of O(n) where n is the total number of elements in the CircularLinkedList() instance.

Parameters:value (Object) – The value to be searched for in the CircularLinkedList() instance.
Returns:True if the given value exists in the CircularLinkedList() instance, and False otherwise.
Return type:bool

Examples

>>> cll = CircularLinkedList([1, 3, 5])
>>> 1 in cll
True
>>> 0 in cll
False
>>> "hello" in cll
False
__delitem__(idx)

Deletes the value at the given index. It does that in time-complexity of O(k%n) where k is the index value and n is the number of elements in the CircularLinkedList() instance.

Parameters:idx (int) – An integer pointing to the index where the node that should be removed.
Raises:IndexError: – If the given index is either negative or out of the boundaries.

Examples

>>> cll = CircularLinkedList([1, 2, 3])
>>> del cll[0]
>>> cll
┌───┐ ┌───┐
│ 2 │⟶│ 3 │⟶ ┐
└───┘ └───┘  │
  ↑          │
  └──────────┘
>>> del cll[-1]
IndexError: Negative indexing isn't supported with this functinoality!!
>>> del cll[31]  #index is bigger than the instance length
>>> cll
┌───┐
│ 2 │⟶ ┐
└───┘  │
  ↑    │
  └────┘
__eq__(other)

Checks if two CircularLinkedList() instances are equal to each other. And this happens if, and only if, the following two conditions are met:

  1. The two instances are equal in length (same number of elements).

2. Every single element in the first instance is equal, in both value and type, to the opposing element of the other instance.

Parameters:other (CircularLinkedList()) – The other instance that we want to compare with the current one
Returns:True if both instances are equal, and False otherwise.
Return type:bool
Raises:TypeError: – This happens in two cases 1. If the other instance isn’t an instance of CircularLinkedList(). 2. In case one element in the first instance doesn’t match the type of the opposing element in the other instance.

Examples

>>> cll_1 = CircularLinkedList([1, 2, 3])
>>> cll_2 = CircularLinkedList([1, 3, 2])
>>> cll_1 == cll_2
False
>>> cll_1 == cll_1
True
__ge__(other)

Checks if the first CircularLinkedList() instance is greater than or equal to the other instance. And this happens if all elements in the first instance are greater than or equal to the opposing element of the second instance.

Parameters:other (CircularLinkedList()) – The other instance that we want to compare with the current one
Returns:True if the first instance is greater than or equal to the second, and False otherwise.
Return type:bool
Raises:TypeError: – This happens in two cases 1. If the other instance isn’t an instance of CircularLinkedList(). 2. In case one element in the first instance doesn’t match the type of the opposing element in the other instance.

Examples

>>> cll_1 = CircularLinkedList([1, 3, 5])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 >= cll_2
True
>>> cll_1 = CircularLinkedList([1, 3, 2, 1])
>>> cll_2 = CircularLinkedList([1, 3, 2])
>>> cll_1 >= cll_2
True
>>> cll_1 = CircularLinkedList([1, 2])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 >= cll_2
False
>>> cll_1 = CircularLinkedList([5, 2, 1])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 >= cll_2
False
>>> cll_1 = CircularLinkedList([1, 2, 3])
>>> cll_2 = CircularLinkedList([1, 2, 3])
>>> cll_1 >= cll_2
True
__getitem__(idx)

Retrieves the element at the given index. The given index must be a zero-based int. This method doesn’t support neither negative indexing nor slice objects. This method does that in time-complexity of O(k%n) where k is the given index and n is the number of elements found in the CircularLinkedList() instance.

Parameters:

idx (int) – The index to be used to retrieve value from CircularLinkedList() instance.

Returns:

It returns the value stored at this the given index.

Return type:

object

Raises:
  • TypeError: – If the given index isn’t int.
  • IndexError: – If CircularLinkedList() instance is empty.

Examples

>>> cll = CircularLinkedList([1, 2, 3, 4, 5])
>>> cll[0]
1
>>> cll[-2]
4
>>> cll[10]
1

Note

Notice that the only case this method raises an IndexError is when the CircularLinkedList() instance is empty. Other than that, the method will keep iterating over the CircularLinkedList() instance till it reaches the given index. That’s why even though the previous CircularLinkedList() instance is five-elements long, the method doesn’t raise and IndexError when trying to retrieve the 10th element.

__gt__(other)

Checks if the first CircularLinkedList() instance is greater than the other instance. And this happens if all elements in the first instance are equal with at least one element greater than the opposing element of the second instance.

Parameters:other (CircularLinkedList()) – The other instance that we want to compare with the current one
Returns:True if the first instance is greater than the second, and False otherwise.
Return type:bool
Raises:TypeError: – This happens in two cases 1. If the other instance isn’t an instance of CircularLinkedList(). 2. In case one element in the first instance doesn’t match the type of the opposing element in the other instance.

Examples

>>> cll_1 = CircularLinkedList([1, 3, 5])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 > cll_2
True
>>> cll_1 = CircularLinkedList([1, 3, 2, 1])
>>> cll_2 = CircularLinkedList([1, 3, 2])
>>> cll_1 > cll_2
True
>>> cll_1 = CircularLinkedList([1, 2])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 > cll_2
False
>>> cll_1 = CircularLinkedList([5, 2, 1])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 > cll_2
False
>>> cll_1 = CircularLinkedList([1, 2, 3])
>>> cll_2 = CircularLinkedList([1, 2, 3])
>>> cll_1 > cll_2
False
__init__(iterable=None)

Initializes a CircularLinkedList() instance using an optional iterable in time-complexity of O(n) where n is the number of elements inside the given iterable.

Parameters:

iterable (iterable, optional) – An iterable python object that implements the __iter__ method. For example, list and tuple are both iterables.

Raises:
  • TypeError: – It can be raised in two cases
    1. In case the given object isn’t iterable.
    2. If one of the iterable elements is an Extra object.
  • ValueError: – If one of the iterable elements is None.

Examples

>>> cll = CircularLinkedList([10, -5, 7, 9])
>>> cll
┌────┐ ┌────┐ ┌───┐ ┌───┐
│ 10 │⟶│ -5 │⟶│ 7 │⟶│ 9 │⟶ ┐
└────┘ └────┘ └───┘ └───┘  │
   ↑                       │
   └───────────────────────┘

Using an iterable object with None as one of its elements will raise ValueError

>>> CircularLinkedList([2, None])
ValueError: Can't use `None` as an element within             `extra.CircularLinkedList()`!!

Using a non-iterable object will raise TypeError

>>> CircularLinkedList(2)
TypeError: The given object isn't iterable!!

Using nested CircularLinkedList objects will raise TypeError as well:

>>> cll_1 = CircularLinkedList([1])
>>> cll_2 = CircularLinkedList([1, cll_1])
TypeError: Can't create `extra.CircularLinkedList()` using             `extra.CircularLinkedList()`!!

Note

Since most of the data structures found in this package are iterables, then you can use this classmethod to convert from one data structure to CircularLinkedList just like so:

>>> ll = LinkedList([2, 5])
>>> cll = CircularLinkedList(ll)
>>> cll
┌───┐ ┌───┐
│ 2 │⟶│ 5 │⟶ ┐
└───┘ └───┘  │
  ↑          │
  └──────────┘
__iter__()

Iterates over the CircularLinkedList() instance and returns a generator in time-complexity of O(n) where n is the number of elements in the CircularLinkedList() instance.

Yields:generator – The value of each node in the instance.

Examples

>>> cll = CircularLinkedList([1, 2, 3])
>>> for item in cll:
...     print(item)
1
2
3
__le__(other)

Checks if the first CircularLinkedList() instance is less than or equal to the other instance. And this happens if all elements in the first instance are equal or less than the opposing elements of the second instance.

Parameters:other (CircularLinkedList()) – The other instance that we want to compare with the current one
Returns:True if the first instance is less than or equal to the second instance, and False otherwise.
Return type:bool
Raises:TypeError: – This happens in two cases 1. If the other instance isn’t an instance of CircularLinkedList(). 2. In case one element in the first instance doesn’t match the type of the opposing element in the other instance.

Examples

>>> cll_1 = CircularLinkedList([1, 3, 2])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 <= cll_2
True
>>> cll_1 = CircularLinkedList([1, 3])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 <= cll_2
True
>>> cll_1 = CircularLinkedList([1, 5])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 <= cll_2
False
>>> cll_1 = CircularLinkedList([5, 2, 1])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 <= cll_2
False
>>> cll_1 = CircularLinkedList([1, 2, 3])
>>> cll_2 = CircularLinkedList([1, 2, 3])
>>> cll_1 <= cll_2
True
__len__()

Gets the length of the CircularLinkedList() in constant time.

Returns:The length of the CircularLinkedList() instance. By Length, I mean the number of nodes of in the instance.
Return type:int

Examples

>>> cll = CircularLinkedList()
>>> len(cll)
0
>>> cll = CircularLinkedList((2, 5, 0))
>>> len(cll)
3
__lt__(other)

Checks if the first CircularLinkedList() instance is less than the other instance. And this happens if all elements in the first instance are equal with at least one element less than the opposing element of the second instance.

Parameters:other (CircularLinkedList()) – The other instance that we want to compare with the current one
Returns:True if the first instance is less than the second, and False otherwise.
Return type:bool
Raises:TypeError: – This happens in two cases 1. If the other instance isn’t an instance of CircularLinkedList(). 2. In case one element in the first instance doesn’t match the type of the opposing element in the other instance.

Examples

>>> cll_1 = CircularLinkedList([1, 3, 2])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 < cll_2
True
>>> cll_1 = CircularLinkedList([1, 3])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 < cll_2
True
>>> cll_1 = CircularLinkedList([1, 5])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 < cll_2
False
>>> cll_1 = CircularLinkedList([5, 2, 1])
>>> cll_2 = CircularLinkedList([1, 3, 3])
>>> cll_1 < cll_2
False
>>> cll_1 = CircularLinkedList([1, 2, 3])
>>> cll_2 = CircularLinkedList([1, 2, 3])
>>> cll_1 < cll_2
False
__ne__(other)

Checks if two CircularLinkedList() instances are NOT equal to each other. And this happens if, and only if, either one of the following two conditions is satisfied:

  1. The two instances are NOT equal in length (number of elements).

2. Just one element in the first instance is NOT equal, in either value or type, to the opposing element of the other instance.

Parameters:other (CircularLinkedList()) – The other instance that we want to compare with the current one
Returns:True if both instances are NOT equal, and False otherwise.
Return type:bool
Raises:TypeError: – This happens in two cases 1. If the other instance isn’t an instance of CircularLinkedList(). 2. In case one element in the first instance doesn’t match the type of the opposing element in the other instance.

Examples

>>> cll_1 = CircularLinkedList([1, 2, 3])
>>> cll_2 = CircularLinkedList([1, 3, 2])
>>> cll_1 != cll_2
True
>>> cll_1 != cll_1
False
__repr__()

Represents the CircularLinkedList() instance as a string.

Returns:The string-representation of the CircularLinkedList() instance.
Return type:str

Example

>>> cll = CircularLinkedList([20, 77, 10, 6, 2])
>>> cll
┌────┐ ┌────┐ ┌────┐ ┌───┐ ┌───┐
│ 20 │⟶│ 77 │⟶│ 10 │⟶│ 6 │⟶│ 2 │⟶ ┐
└────┘ └────┘ └────┘ └───┘ └───┘  │
   ↑                              │
   └──────────────────────────────┘
__setitem__(idx, item)

Replaces the value at the given index with the given item. It does that in time-complexity of O(k%n) where k is the index value and n is the number of elements in the CircularLinkedList() instance.

Parameters:
  • idx (int) – An integer pointing to the index at which the given value should be inserted.
  • item (object) – An object to be inserted.
Raises:
  • IndexError: – If the given index is either negative or out of the boundaries.
  • ValueError: – If the given object is None.
  • TypeError: – This get raised in one of the following cases:
    1. If the given index type is not int.
    2. If the given object is an instance of Extra.

Examples

>>> cll = CircularLinkedList([1, 2, 3])
>>> cll[0] = 10
>>> cll[2] = 30
>>> cll
┌────┐ ┌───┐ ┌────┐
│ 10 │⟶│ 2 │⟶│ 30 │⟶ ┐
└────┘ └───┘ └────┘  │
   ↑                 │
   └─────────────────┘
>>> cll[-1] = 0
IndexError: Negative indexing isn't supported with this functinoality!!
>>> cll[31] = 20 #index is bigger than the instance length
>>> cll
┌────┐ ┌────┐ ┌────┐
│ 10 │⟶│ 20 │⟶│ 30 │⟶ ┐
└────┘ └────┘ └────┘  │
   ↑                  │
   └──────────────────┘
add_end(item)

Adds the given value at the tail of the CircularLinkedList() instance in time-complexity of O(n) where n is the number of elements in the instance.

Parameters:

item (object) – The value to be inserted at the CircularLinkedList() tail.

Raises:
  • TypeError: – If the given item is an instance of Extra.
  • ValueError: – If the given item is None.

Examples

>>> cll = CircularLinkedList([1, 2, 3])
>>> cll.add_end(10)
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌────┐
│ 1 │⟶│ 2 │⟶│ 3 │⟶│ 10 │⟶ ┐
└───┘ └───┘ └───┘ └────┘  │
  ↑                       │
  └───────────────────────┘
add_front(item)

Adds the given value at the head of the CircularLinkedList() instance in constant time.

Parameters:

item (object) – The value to be inserted at the CircularLinkedList() head.

Raises:
  • TypeError: – If the given item is an instance of Extra.
  • ValueError: – If the given item is None.

Examples

>>> cll = CircularLinkedList([1, 2, 3])
>>> cll.add_front(10)
>>> cll
┌────┐ ┌───┐ ┌───┐ ┌───┐
│ 10 │⟶│ 1 │⟶│ 2 │⟶│ 3 │⟶ ┐
└────┘ └───┘ └───┘ └───┘  │
   ↑                      │
   └──────────────────────┘
clear()

Removes all nodes within the CircularLinkedList() in constant time.

Example

>>> cll = CircularLinkedList([1, 2, 3])
>>> cll
┌───┐ ┌───┐ ┌───┐
│ 1 │⟶│ 2 │⟶│ 3 │⟶ ┐
└───┘ └───┘ └───┘  │
  ↑                │
  └────────────────┘
>>> cll.clear()
>>> cll.is_empty()
True
>>> cll
┌─

└─
copy()

Copies the CircularLinkedList() instance in a shallow-manner.

Returns:The shallow copy of the original instance.
Return type:CircularLinkedList()

Example

>>> cll = CircularLinkedList()
>>> cll.add_end(10)
>>> cll.add_end(20)
>>> cll
┌────┐ ┌────┐
│ 10 │⟶│ 20 │⟶ ┐
└────┘ └────┘  │
   ↑           │
   └───────────┘
>>> cll.copy()
┌────┐ ┌────┐
│ 10 │⟶│ 20 │⟶ ┐
└────┘ └────┘  │
   ↑           │
   └───────────┘
count(value)

Counts the number of occurrence the given value is in the CircularLinkedList() instance.

Parameters:value (object) – The object to count its occurrences
Returns:The number of times the given value is found in the CircularLinkedList() instance. And 0 if it wasn’t found.
Return type:int

Example

>>> cll = CircularLinkedList([0, 1, 1, 2, 3, 5])
>>> cll.count(3)
1
>>> cll.count(1)
2
>>> cll.count("he")
0
extend(other)

Extends the current CircularLinkedList() instance by appending the elements of the other CircularLinkedList() instance in time- complexity of O(n+m) where n is the number of elements in the original instance and m is the number of elements in the other instance.

Parameters:other (CircularLinkedList()) – The CircularLinkedList() instance whose elements will be appended
Raises:TypeError: – If the given object isn’t a CircularLinkedList() instance.

Example

>>> cll_1 = CircularLinkedList([1, 2])
>>> cll_1
┌───┐ ┌───┐
│ 1 │⟶│ 2 │⟶ ┐
└───┘ └───┘  │
  ↑          │
  └──────────┘
>>> cll_2 = CircularLinkedList([3, 4, 5])
>>> cll_1.extend(cll_2)
>>> cll_1
┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 1 │⟶│ 2 │⟶│ 3 │⟶│ 4 │⟶│ 5 │⟶ ┐
└───┘ └───┘ └───┘ └───┘ └───┘  │
  ↑                            │
  └────────────────────────────┘
>>> cll_1.extend([6, 7])
TypeError: Type Mismatch! Can't extend `extra.CircularLinkedList()`             with `<class 'list'>`!!
insert(idx, item)

Insertd a value to the CircularLinkedList() instance at a position defined by the given index.

Parameters:
  • idx (int) – An integer pointing to the index at which the given value should be inserted.
  • item (object) – An object to be inserted.
Raises:
  • IndexError: – This happens only if the index is less than zero (-ve).
  • TypeError: – This happens in one of the following cases:
    1. If the given index isn’t integer.
    2. If the given item is an instance of Extra.
  • ValueError: – If the given item is None.

Example

>>> cll = CircularLinkedList([1, 2, 3])
>>> cll.insert(1, item=10)
>>> cll
┌───┐ ┌────┐ ┌───┐ ┌───┐
│ 1 │⟶│ 10 │⟶│ 2 │⟶│ 3 │⟶ ┐
└───┘ └────┘ └───┘ └───┘  │
  ↑                       │
  └───────────────────────┘
>>> cll.insert(15, item=8)  #index is bigger than instance length
>>> cll
┌───┐ ┌───┐ ┌────┐ ┌───┐ ┌───┐
│ 8 │⟶│ 1 │⟶│ 10 │⟶│ 2 │⟶│ 3 │⟶ ┐
└───┘ └───┘ └────┘ └───┘ └───┘  │
  ↑                             │
  └─────────────────────────────┘
>>> cll.insert(1, item=None)
>>> cll
ValueError: Can't use `None` as an element within             `extra.CircularLinkedList()`!!
>>> cll.insert(-1, item=100)
>>> cll
IndexError: Negative indexing isn't supported with this functinoality!!
is_empty()

Checks if CircularLinkedList() instance is empty or not in constant time.

Returns:A boolean flag showing if the CircularLinkedList() instance is empty or not. True shows that this instance is empty and False shows it’s not empty.
Return type:bool

Example

>>> cll = CircularLinkedList()
>>> cll.is_empty()
True
>>> cll.add_front(5)
>>> cll.is_empty()
False
remove(value, all=True)

Removes a single node or multiple nodes (in case of all being True) whose value equal to the given value from the CircuarLinkedList() instance.

Parameters:
  • value (object) – The value to be removed from the CircularLinkedList() instance.
  • all (bool) – A flag (default: True); if True, all occurrences of the given value are remove. If False, only the first occurrence is removed.
Raises:
  • ValueError: – If The given value is None.
  • TypeError: – This get raised in one of the following cases:
    1. If the type of the all flag isn’t boolean.
    2. If the given value is an instance of Extra class.

Example

>>> cll = CircularLinkedList([1, 2, 3, 2, 2])
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 1 │⟶│ 2 │⟶│ 3 │⟶│ 2 │⟶│ 2 │⟶ ┐
└───┘ └───┘ └───┘ └───┘ └───┘  │
  ↑                            │
  └────────────────────────────┘
>>> cll.remove(2, all=False)
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 1 │⟶│ 3 │⟶│ 2 │⟶│ 2 │⟶ ┐
└───┘ └───┘ └───┘ └───┘  │
  ↑                      │
  └──────────────────────┘
>>> cll.remove(10) #does nothing
>>> cll.remove(2)
>>> cll
┌───┐ ┌───┐
│ 1 │⟶│ 3 │⟶ ┐
└───┘ └───┘  │
  ↑          │
  └──────────┘
remove_end()

Removes the value at the tail of the CircularLinkedList() instance in time-complexity of O(k%n) where k is the index value and n is the number of elements in the CircularLinkedList() instance.

Examples

>>> cll = CircularLinkedList([1, 2, 3])
>>> cll.remove_end()
>>> cll
┌───┐ ┌───┐
│ 1 │⟶│ 2 │⟶ ┐
└───┘ └───┘  │
  ↑          │
  └──────────┘
>>> cll.remove_end()
>>> cll
┌───┐
│ 1 │⟶ ┐
└───┘  │
  ↑    │
  └────┘
remove_front()

Removes the value at the head of the CircularLinkedList() instance in constant time.

Examples

>>> cll = CircularLinkedList([1, 2, 3])
>>> cll.remove_front()
>>> cll
┌───┐ ┌───┐
│ 2 │⟶│ 3 │⟶ ┐
└───┘ └───┘  │
  ↑          │
  └──────────┘
>>> cll.remove_front()
>>> cll
┌───┐
│ 3 │⟶ ┐
└───┘  │
  ↑    │
  └────┘
reverse()

Reverses the whole CircularLinkedList() instance in time-complexity of O(n) where n is the number of elements in the instance.

Returns:The reversed CircularLinkedList() instance.
Return type:CircularLinkedList()

Example

>>> cll = CircularLinkedList([1, 2, 3, 4])
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 1 │⟶│ 2 │⟶│ 3 │⟶│ 4 │⟶ ┐
└───┘ └───┘ └───┘ └───┘  │
  ↑                      │
  └──────────────────────┘
>>> cll.reverse()
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 4 │⟶│ 3 │⟶│ 2 │⟶│ 1 │⟶ ┐
└───┘ └───┘ └───┘ └───┘  │
  ↑                      │
  └──────────────────────┘
rotate_left(distance, inplace=True)

Rotates the CircularLinkedList() instance to the left by a number of times defined by the distance. If inplace=True, it does the rotation in-place. If not, it returns the rotated instance. The time-compelxity of this method is of O(k%n) where k is the index and n is the number of elements in the CircularLinkedList() instance.

Parameters:
  • distance (int) – The rotation distance to the left.
  • inplace (bool) – A flag to determine if the rotation is going to be in-place or not. (default True).
Returns:

The rotated instance if inplace=True

Return type:

CircularLinkedList()

Examples

>>> cll = CircularLinkedList([1, 2, 3, 4])
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 1 │⟶│ 2 │⟶│ 3 │⟶│ 4 │⟶ ┐
└───┘ └───┘ └───┘ └───┘  │
  ↑                      │
  └──────────────────────┘
>>> cll.rotate_left(1)
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 2 │⟶│ 3 │⟶│ 4 │⟶│ 1 │⟶ ┐
└───┘ └───┘ └───┘ └───┘  │
  ↑                      │
  └──────────────────────┘
>>> # it works just fine when the distance is bigger than the
>>> # length of the circular linked list instance
>>> cll.rotate_left(10)
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 4 │⟶│ 1 │⟶│ 2 │⟶│ 3 │⟶ ┐
└───┘ └───┘ └───┘ └───┘  │
  ↑                      │
  └──────────────────────┘
rotate_right(distance, inplace=True)

Rotates the CircularLinkedList() instance to the right by a number of times defined by the given distance. If inplace=True, it does the rotation in-place. If not, it returns the rotated instance. The time- compelxity of this method is O(k%n) where k is the index and n is the number of elements in the CircularLinkedList() instance.

Parameters:
  • distance (int) – The rotation distance to the right.
  • inplace (bool) – A flag to determine if the rotation is going to be in-place or not. (default True).
Returns:

The rotated instance if inplace=True

Return type:

CircularLinkedList()

Examples

>>> cll = CircularLinkedList([1, 2, 3, 4])
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 1 │⟶│ 2 │⟶│ 3 │⟶│ 4 │⟶ ┐
└───┘ └───┘ └───┘ └───┘  │
  ↑                      │
  └──────────────────────┘
>>> cll.rotate_right(1)
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 4 │⟶│ 1 │⟶│ 2 │⟶│ 3 │⟶ ┐
└───┘ └───┘ └───┘ └───┘  │
  ↑                      │
  └──────────────────────┘
>>> # it works just fine when the distance is bigger than the
>>> # length of the circular linked list instance
>>> cll.rotate_right(14)
>>> cll
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ 2 │⟶│ 3 │⟶│ 4 │⟶│ 1 │⟶ ┐
└───┘ └───┘ └───┘ └───┘  │
  ↑                      │
  └──────────────────────┘
split(idx)

Splits the CircularLinkedList() instance into two instances based on the given index in time-complexity of O(min(k,n/2)) where k is the index and n is the number of elements in the original instance. We can consider idx as the start index of the second CircularLinkedList() after splitting. If idx=0, the first returned CircularLinkedList() will be empty while the second returned CircularLinkedList() will be the same length as the original.

Parameters:

idx (int) – A positive integer pointing to the index at which the CircularLinkedList() instance should be split.

Returns:

  • CircularLinkedList() – The left CircularLinkedList() instance returned after split.
  • CircularLinkedList() – The right CircularLinkedList() instance returned after split

Raises:
  • TypeError: – If the given index isn’t int.
  • IndexError: – If the given index is either negative or out of the CircularLinkedList() boundaries.

Examples

>>> cll = CircularLinkedList([1, 2, 3])
>>> cll
┌───┐ ┌───┐ ┌───┐
│ 1 │⟶│ 2 │⟶│ 3 │⟶ ┐
└───┘ └───┘ └───┘  │
  ↑                │
  └────────────────┘
>>> left, right = cll.split(1)
>>> left
┌───┐
│ 1 │⟶ ┐
└───┘  │
  ↑    │
  └────┘
>>> right
┌───┐ ┌───┐
│ 2 │⟶│ 3 │⟶ ┐
└───┘ └───┘  │
  ↑          │
  └──────────┘
to_list()

Converts the CircularLinkedList() instance to a list in time- complexity of O(n) where n is the number of elements in the CircularLinkedList() instance.

Returns:A list object containing the same elements as the CircularLinkedList() instance.
Return type:list

Example

>>> cll = CircularLinkedList()
>>> cll.add_front(20)
>>> cll.add_front(10)
>>> cll.add_end(30)
>>> cll
┌────┐ ┌────┐ ┌────┐
│ 10 │⟶│ 20 │⟶│ 30 │⟶ ┐
└────┘ └────┘ └────┘  │
   ↑                  │
   └──────────────────┘
>>> cll.to_list()
[10, 20, 30]