Python Circular Buffer

Python Circular Buffer

  1. Efficient Circular Buffer in Python
  2. Implement Circular Buffer in Python
  3. Advantages of Python Circular Buffer
  4. Disadvantages of Python Circular Buffer
  5. Conclusion

A circular buffer is the other name for a ring buffer. A buffer is a data structure that uses a single, fixed-size buffer as if it were connected end-to-end.

This structure helps manage data streams in which new data can be constantly added at one end, and old data can be removed from the other. When the buffer is full, new data will overwrite the oldest data.

Efficient Circular Buffer in Python

An efficient circular buffer is a data structure that allows for efficient insertion and deletion of data.

A circular buffer is typically implemented as an array. The array head pointer points to the first element, and the tail pointer indicates the last element in the array.

The head and tail pointers wrap around when they reach the end of the array. Insertion into a circular buffer is done by incrementing the head pointer and writing the data to the array at that location.

Deletion from a circular buffer is done by incrementing the tail pointer. That data is not deleted from the array, but the head and tail pointers effectively skip over it.

A circular buffer is an efficient data structure because it only requires a fixed amount of memory. It is also easy to implement.

class Buffer:
    def __init__(self, size):
        self.data = [None for i in range(size)]

    def append(self, x):
        self.data.pop(0)
        self.data.append(x)

    def get(self):
        return self.data

buf = Buffer(4)
for i in range(10):
    buf.append(i)
    print(buf.get())

Output:

[None, None, None, 0]
[None, None, 0, 1]
[None, 0, 1, 2]
[0, 1, 2, 3]
[1, 2, 3, 4]
[2, 3, 4, 5]
[3, 4, 5, 6]
[4, 5, 6, 7]
[5, 6, 7, 8]
[6, 7, 8, 9]

Implement Circular Buffer in Python

There are many ways to implement efficient circular buffers in Python. One common approach is to use a collections.dequeue object designed to efficiently support removing and adding elements from both the front and back of the queue.

Another method is to use a list and keep track of the head and tail indices separately.

If you want to know which approach is best, it depends on the application’s specific requirements. For example, if elements need to be added and removed from the buffer frequently, and order is not essential, then the dequeue approach may be best.

On the other hand, if elements are only added to the buffer once and then read out many times, or if the order is essential, then the list approach may be better.

Implement Circular Queue Using collections.enqueue and collections.dequeue in Python

First, we will add values in the queue using the function collections.enqueue. Then, we can use collection.dequeue in the circular queue for deleting an element from the queue.

To understand its working, let’s look at the practical example of the circular queue in Python.

Example Code:

# implememting circular queue in python
class CircularQueue():

    def __init__(collections, k):
        collections.k = k
        collections.queue = [None] * k
        collections.head = collections.tail = -1

    # this function will insert (Enqueue) an element into the circular queue
    def enqueue1(collections, data):

        if ((collections.tail + 1) % collections.k == collections.head):
            print("The queue is full\n")

        elif (collections.head == -1):
            collections.head = 0
            collections.tail = 0
            collections.queue[collections.tail] = data
        else:
            collections.tail = (collections.tail + 1) % collections.k
            collections.queue[collections.tail] = data

    # this function will delete (dequeue) an element from the circular
    def dequeue1(collections):
        if (collections.head == -1):
            print("The circular queue is empty\n")

        elif (collections.head == collections.tail):
            temp = collections.queue[collections.head]
            collections.head = -1
            collections.tail = -1
            return temp
        else:
            temp = collections.queue[collections.head]
            collections.head = (collections.head + 1) % collections.k
            return temp

     # This function is used to print the queue
    def printCQueue1(collections):
        if(collections.head == -1):
            print("Circular queue is empty")

        elif (collections.tail >= collections.head):
            for i in range(collections.head, collections.tail + 1):
                print(collections.queue[i], end=" ")
            print()
        else:
            for i in range(collections.head, collections.k):
                print(collections.queue[i], end=" ")
            for i in range(0, collections.tail + 1):
                print(collections.queue[i], end=" ")
            print()


obj = CircularQueue(5)

# adding data to the queue
for i in range(1, 6):
    obj.enqueue1(i)

print("Display queue")
obj.printCQueue1()

# removing data from the queue
print("\nDelete Value:", obj.dequeue1())
print("Delete Value:", obj.dequeue1())


print("\nTwo values were deleted from the queue")
print("The new queue has 3 values now")
obj.printCQueue1()

Output:

Display queue
1 2 3 4 5

Delete Value: 1
Delete Value: 2

Two values were deleted from the queue
The new queue has 3 values now
3 4 5

Advantages of Python Circular Buffer

There are many advantages to using a circular buffer when working with data in Python.

  1. One advantage is that it can be used to store data in a First In, First Out (FIFO) manner. This can help when you need to process data in the original order it was received.
  2. Another advantage is that a circular buffer can store data in a Last In, First Out (LIFO) manner. This will be good when you need to process data in the reverse order that it was received.
  3. Additionally, a circular buffer can be used to store data in a random access manner. This can be helpful when you need to access data quickly and randomly.

Disadvantages of Python Circular Buffer

There are some disadvantages to using a circular buffer in Python.

  1. First, it is not possible to randomly access elements in the buffer. This can cause difficulty in working with data that is not in a linear order.
  2. Second, the size of the buffer is fixed. This can cause an issue if you need to store more data than the buffer can hold.
  3. Finally, circular buffers can be more difficult to debug than other data structures.

Conclusion

Python circular buffer is a speedy and efficient way to store data. A circular data buffer is a queue that can be used as a container that holds a single object.

A circular buffer is typically used when data is constantly added and removed, such as in a video game or audio processing. It can be implemented with a single pointer, whereas a linear queue requires two pointers.

A circular buffer can be easily extended to multiple queues, allowing concurrent data access.

Zeeshan Afridi avatar Zeeshan Afridi avatar

Zeeshan is a detail oriented software engineer that helps companies and individuals make their lives and easier with software solutions.

LinkedIn

Related Article - Python Buffer

  • Buffer in Python