# Circular Linked Lists Introduction and Application

In this article, we will provide an overview of linked lists. How they function, their attributes and examples of important applications that can benefit from using circular linked lists as the underlying data structure. We will also showcase some Python code samples to demonstrate how circular linked lists can be implemented.

## What is Circular Linked List?

Linked lists are one of the data structures used in computer science and programming. They offer a way to store and organize data that requires frequent insertion and removal operations.

A circular linked list is a variation of the linked list structure where the last node is connected back to the node, creating an arrangement. This difference from linked lists gives linked lists unique characteristics and advantages for specific use cases.

Understanding linked lists is valuable for any programmer as they are commonly encountered in operating systems, databases and networking. Their cyclic nature aligns well with real-world scenarios like ring buffers, looped media playback, and periodic events. By the end of this article, you will have a solid grasp of circular linked list fundamentals and be able to assess when they may be the appropriate choice over arrays, regular linked lists or other data structures for an application.

### Let's understand the Circular Linked List in Detail.

A circular linked list is a variant of a linked list in which the last node points back to the first node, forming a continuous circle. This differs from regular singly or doubly linked lists that end with a null pointer marking the end.

The main advantage of a circular linked list is that it has no ends to traverse. This allows continuous indefinite forward and backward traversal in a loop.

### Some key properties of circular linked lists:

• The first node points to the second node, the second node to the third and so on, until the last node, which points back to the first node. This creates a non-ending loop.
• There is no null reference at the end. The cycle continues endlessly.
• They can be either singly linked (each node has one pointer) or doubly linked (each node has two pointers - to next and previous)
• The circular list has no starting or ending node. Every node can be considered a head and tail node.
• Useful for implementing fixed-size buffers and queues. New data overwrites the oldest data after a circular traversal.
• It is often used to represent repetitive events or collections with a fixed size but no real start or end, like a deck of cards.
• Algorithms need to include checks for the circular connectivity to prevent infinite loops during traversal. The current node's next pointing back to the head signals end.
• Constant O(1) time insertion and deletion since pointers just need reassignment without shifting elements. Access is O(n).
• Circular doubly linked lists allow traversing the list in both directions efficiently.

In summary, circular linked lists provide efficient in-place operations and infinite traversal due to their circular nature. They are useful for buffers, histories, scheduling, and other domains requiring fixed-size data structures.

Efficient memory usage

• The circular connectivity allows linked lists to reuse the same nodes, storing data in a fixed space. No dynamic resizing is needed. This makes circular lists useful for fixed-size buffers and queues.

Infinite traversal

• The circular nature allows indefinite traversal of the list forward and backwards by following pointers. Useful for data requiring repeated access like game turns or audio playlists.

Constant time inserts/deletes

• Adding or removing nodes simply requires reassigning a few pointers rather than shifting elements down or finding insertion points.

Preallocated memory

• Circular lists allow the preallocation of nodes upfront since the size is fixed. This avoids the runtime overhead of dynamically requesting more memory.

Faster access than arrays

• Retrieving the next or previous element is fast with pointer chasing. Arrays require calculating index offsets.

Hidden ends

• The looped structure hides the actual start and end positions. Algorithms can treat any node as the first element.

History tracking

• Circular lists provide an efficient way to store the history of events or states in a fixed buffer that gets overwritten after reaching capacity.

Looped/repeated processing

• Good for modelling circular processes like round-robin scheduling. Nodes can be continuously traversed with no distinct end.

Bounded resource usage

• Capping the list size bounds memory usage. Old data gets automatically overwritten by new after traversing full circle.

Simplified code

• Algorithms on circular lists are simpler. No need for special handling for off-by-one errors or ends.

The main advantages are efficient memory usage, fast inserts and deletes, preallocation, infinite traversal, hidden ends, history tracking, and simplified circular algorithms. Circular lists shine when data exhibits a circular or looping pattern.

### Applications of Circular Linked Lists

Ring Buffers

Ring buffers are fixed-size buffers that work in a first-in, first-out (FIFO) order, overwriting old data with new data when capacity is reached. Circular linked lists provide an efficient underlying data structure to implement ring buffers. As elements are added, the linked list grows until reaching capacity. Then, appending the next element loops the list back to the head, overwriting the oldest entry. This cyclic overwriting behaviour makes circular lists ideal for ring buffers. The constant time insertions and deletions mean adding or removing elements is fast, even at capacity. The circular structure also allows the preallocation of buffer size without wasting memory. The cyclic connectivity and constant time operations make circular linked lists well-suited for implementing ring buffers used in-memory caching, network data buffers, filesystem buffers, etc.

Browser History

Web browsers use circular linked lists to store the pages a user has visited in chronological order, enabling the back/forward navigation buttons. As more pages are visited, older pages shift back in the list until they are overwritten in a FIFO manner once capacity is reached. The circular list structure guarantees pages remain in order but are eventually overwritten after the list loops back to the head. The doubly linked nature also allows efficient bidirectional traversal of history. Circular lists are preferred over arrays for browser history since insertions are faster. Overall, circular linked lists are ideal for storing browser history as their cyclic structure maintains a fixed size and ordered buffer of pages in FIFO order.

Round Robin Scheduling

In round-robin scheduling, processes are allotted CPU time slices in a circular rotating fashion. This equal CPU sharing can be efficiently modelled using a circular linked list of processes. As the scheduler loops through the list, each process gets a turn being executed. The circular structure ensures no endpoint, and processes are revisited in fair cyclic order. Insertion and removal of processes are also easy and fast. The infinite traversal and constant time insertions/deletions make circular linked lists well-suited for modelling round-robin scheduling systems used in operating systems.

Media Playlists

Media applications use circular-linked lists to store and playback audio/video files in a continuous looping playlist. The cyclic structure provides seamless looping back to the starting media after playing the last element. Doubly linked lists further allow backwards seeking. Playlist additions are fast and memory efficient due to just updating pointers. Overall, the circular looping and efficient insertions allow circular linked lists to effectively store and playback looping media playlists.

Turn-based Games

Games where players take turns sequentially can model the turn order using a circular linked list, advancing to the next player after each turn. The circular structure naturally models the concept of cyclical turns without distinct starting or ending points. Inserting and removing players is also fast with pointer updates. Circular lists are often preferred over arrays in gaming due to the flexibility and speed of insertions/deletions. The infinite traversal and fixed-size possibilities are also well-suited to repeating turn-based games.

OS Process Scheduling

An operating system can implement round-robin scheduling by keeping processes in a circular linked list. The scheduler loops through this list, giving each process a time slice before moving to the next. This continues cyclically in a loop. The circular list provides an efficient way to model the round-robin looping sequence. The addition and removal of processes are also fast. Overall, circular linked lists allow simple modelling of repetitive fair scheduling in operating systems.

Card Games

Card games can be implemented by modelling the deck of cards as a circular linked list. Shuffling can be simulated by randomly pointing the head to any position in the deck. Dealing cards just removes elements from any position. The circular list maintains the Deck continuity after shuffling and dealing. Doubly linked lists allow reversing dealing order. Overall, circular lists nicely encapsulate the circular sequencing in card decks.

Matrix Traversal

Matrices can be traversed in patterns like spirals or concentric rectangles using circular linked lists to store the path sequence. The circular list naturally models the looping circular shape without the need for special logic at the ends. Complex nested loops are avoided. Adding or removing cells is also fast. So, circular lists simplify implementing matrix traversal algorithms.

Circular Buffers

Input data from devices can be collected in a fixed-size circular buffer implemented via a circular linked list. New data is appended, overwriting the oldest data in FIFO order after capacity is reached. The innate circular looping behaviour makes circular lists ideal for these circular buffers used in device drivers, data acquisition systems, queues, etc.

DNA Analysis

Circular DNA structures like plasmids have no real start or endpoints. They can be analyzed by treating the sequence as a circular linked list to identify genes, codons, motifs, etc. The circular connectivity simplifies algorithms by removing special edge cases. Insertions and deletions are also fast for mutational analysis. So, circular lists model circular DNA effectively.

### Python Implementation of Circular Linked Lists

Output:

Explanation

1. The Node class defines each node object holding data and a next pointer.
2. CircularSinglyLinkedList class contains a head pointer pointing to the first node.
3. prepend(data) inserts new node at head:
• Create a new node with the given data
• Point its next to the current head
• Find the tail node (before the head) and point the tail to the new node
• Update head to new node
4. append(data) inserts at tail:
• Create a new node with the given data
• Find the tail node using the loop
• Point tails next to the new node
• Point new nodes next to the head
5. print_list() prints data in each node:
• Print data and traverse to the next
• Break when next points to head
6. remove(key) deletes node with a given key:
• Special case if the head node
• Otherwise, find prev and node using the loop
• Point prev to node's next
7. len() returns length:
• Initialize count
• Traverse list till reaches back to head
• Return count
8. split_list() splits circular list at midpoint:
• Calculate length
• Traverse first mid nodes using prev, cur pointers
• Break loop at mid-point
• Point prev's next to head (breaks circle)
• Create a new circular list with the remaining nodes
• Print both lists

The key aspects are:

• Properly maintaining circular pointer connections
• Finding tail node before head
• Handling special case of head node
• Breaking circular connection to split list

Using prev cur pointers for traversal and relinking