From 451998f745a51a4e72b7b20cb67897b69e705d62 Mon Sep 17 00:00:00 2001 From: Richa Jaishwal Date: Tue, 5 Nov 2024 15:50:17 +0530 Subject: [PATCH 1/2] Added Circular array --- docs/Circular_array/Application.md | 208 ++++++++++++++++++++++ docs/Circular_array/Introduction.md | 267 ++++++++++++++++++++++++++++ 2 files changed, 475 insertions(+) create mode 100644 docs/Circular_array/Application.md create mode 100644 docs/Circular_array/Introduction.md diff --git a/docs/Circular_array/Application.md b/docs/Circular_array/Application.md new file mode 100644 index 000000000..17b290937 --- /dev/null +++ b/docs/Circular_array/Application.md @@ -0,0 +1,208 @@ +--- +id: circular-array-application +sidebar_position: 2 +title: Applications of Circular Arrays +sidebar_label: Applications of Circular Arrays +description: "Circular arrays are used in various real-world applications for efficient memory usage and continuous data management." +tags: [circular array, applications, data structure, DSA, programming] +--- + +## Common Applications in Real-World Scenarios +- **Network Packet Buffers**: Used in routers to handle packets with limited memory. +- **Operating System Buffers**: Useful for managing I/O data streams. +- **Real-Time Data Logging**: Used to store recent data while continuously overwriting the oldest data. + + +Here is a real-world example where a circular array can be practically applied: + +## Circular Buffer for Logging Events + +This documentation provides the implementations of a circular buffer in Java, C++, and Python. This data structure is commonly used in logging systems to maintain a fixed-size buffer of recent entries, where the oldest entries are overwritten when the buffer becomes full. + +--- + +### Java Code + +```java +import java.util.Arrays; + +public class CircularBuffer { + private String[] buffer; + private int front; + private int rear; + private int size; + private int capacity; + + public CircularBuffer(int capacity) { + this.capacity = capacity; + buffer = new String[capacity]; + front = -1; + rear = -1; + size = 0; + } + + public boolean isEmpty() { + return size == 0; + } + + public boolean isFull() { + return size == capacity; + } + + public void logEvent(String event) { + if (isFull()) { + front = (front + 1) % capacity; // Move front forward if buffer is full + } else { + size++; + } + rear = (rear + 1) % capacity; + buffer[rear] = event; + System.out.println("Logged event: " + event); + } + + public String[] getEvents() { + String[] events = new String[size]; + int index = front == -1 ? 0 : (front + 1) % capacity; + for (int i = 0; i < size; i++) { + events[i] = buffer[index]; + index = (index + 1) % capacity; + } + return events; + } + + public static void main(String[] args) { + CircularBuffer logger = new CircularBuffer(5); + logger.logEvent("Event 1"); + logger.logEvent("Event 2"); + logger.logEvent("Event 3"); + logger.logEvent("Event 4"); + logger.logEvent("Event 5"); + + // Adding more events to show circular behavior + logger.logEvent("Event 6"); // Overwrites oldest + logger.logEvent("Event 7"); + + System.out.println("Logged Events: " + Arrays.toString(logger.getEvents())); + } +} +``` +### C++ Implementation +```cpp +#include +#include +#include + +class CircularBuffer { +private: + std::vector buffer; + int front, rear, size, capacity; + +public: + CircularBuffer(int capacity) : capacity(capacity), front(-1), rear(-1), size(0) { + buffer.resize(capacity); + } + + bool isEmpty() const { + return size == 0; + } + + bool isFull() const { + return size == capacity; + } + + void logEvent(const std::string& event) { + if (isFull()) { + front = (front + 1) % capacity; // Move front forward if buffer is full + } else { + size++; + } + rear = (rear + 1) % capacity; + buffer[rear] = event; + std::cout << "Logged event: " << event << std::endl; + } + + void getEvents() const { + if (isEmpty()) { + std::cout << "No events logged." << std::endl; + return; + } + + int index = front == -1 ? 0 : (front + 1) % capacity; + std::cout << "Logged Events: "; + for (int i = 0; i < size; i++) { + std::cout << buffer[index] << " "; + index = (index + 1) % capacity; + } + std::cout << std::endl; + } +}; + +int main() { + CircularBuffer logger(5); + logger.logEvent("Event 1"); + logger.logEvent("Event 2"); + logger.logEvent("Event 3"); + logger.logEvent("Event 4"); + logger.logEvent("Event 5"); + + // Adding more events to show circular behavior + logger.logEvent("Event 6"); // Overwrites oldest + logger.logEvent("Event 7"); + + logger.getEvents(); + return 0; +} +``` +### Python Implementation + +```python +class CircularBuffer: + def __init__(self, capacity): + self.capacity = capacity + self.buffer = [None] * capacity + self.front = -1 + self.rear = -1 + self.size = 0 + + def is_empty(self): + return self.size == 0 + + def is_full(self): + return self.size == self.capacity + + def log_event(self, event): + if self.is_full(): + self.front = (self.front + 1) % self.capacity # Move front forward if buffer is full + else: + self.size += 1 + self.rear = (self.rear + 1) % self.capacity + self.buffer[self.rear] = event + print(f"Logged event: {event}") + + def get_events(self): + events = [] + index = 0 if self.front == -1 else (self.front + 1) % self.capacity + for _ in range(self.size): + events.append(self.buffer[index]) + index = (index + 1) % self.capacity + return events + + +# Example usage +logger = CircularBuffer(5) +logger.log_event("Event 1") +logger.log_event("Event 2") +logger.log_event("Event 3") +logger.log_event("Event 4") +logger.log_event("Event 5") + +# Adding more events to show circular behavior +logger.log_event("Event 6") # Overwrites oldest +logger.log_event("Event 7") + +print("Logged Events:", logger.get_events()) +``` +### Explanation +These implementations of a circular buffer manage a fixed-size collection where the oldest entries are overwritten when the buffer becomes full. In each version (Java, C++, and Python), the circular buffer uses an array to store entries, along with variables to track the `front`, `rear`, and `size`. When an event (or entry) is logged, the program checks if the buffer is full. If full, the `front` pointer advances to discard the oldest entry, while the `rear` pointer increments to store the new event in a "circular" manner, wrapping around to the start of the array when reaching the end. This approach maintains a constant buffer size, making it ideal for real-time applications like logging systems. Finally, a method retrieves all stored events in the correct order for review. +### Conclusion +Each implementation demonstrates how a circular buffer can manage a fixed-size buffer, retaining only the most recent entries by overwriting the oldest ones when the buffer is full. \ No newline at end of file diff --git a/docs/Circular_array/Introduction.md b/docs/Circular_array/Introduction.md new file mode 100644 index 000000000..964487116 --- /dev/null +++ b/docs/Circular_array/Introduction.md @@ -0,0 +1,267 @@ +--- +id: Circular Array introduction +sidebar_position: 1 +title: Introduction of Circular +sidebar_label: Introduction +description: "A B-tree is a self-balancing tree data structure that maintains sorted data for efficient insertion, deletion, and search operations." +tags: [b-tree, algorithms, problem-solving, DSA, data structure] +--- + +## Introduction + +A **circular array** (or circular buffer) is a linear data structure that wraps around to the beginning once it reaches the end. +It is used in scenarios where we need a fixed-size buffer that can overwrite old data with new data, such as in queue operations +or buffering systems. + +## Key Features +- **Fixed Size:** The array has a fixed capacity. +- **Circular Nature:** When you reach the end, the next element is placed at the beginning of the array. +- **Efficient Usage:** Enables optimal memory usage by reusing space without reallocating the array. + +## Use Cases +- **Circular Queue Implementations:** Useful for implementing queue structures where the oldest data gets replaced by new entries + when capacity is full. +- **Buffering Systems:** Common in audio/video buffering or any system that needs constant data flow with limited memory. + +## Basic Operations +1. **Initialization:** Setting up the array with a fixed size and pointers for start (`front`) and end (`rear`). +2. **Insertion (Enqueue):** Adding an element at the rear and updating the position circularly. +3. **Deletion (Dequeue):** Removing an element from the front and updating the position circularly. +4. **Check Full/Empty Status:** Methods to check if the array is full or empty. + +## Implementation Example (Python) + +Here is an example in Python to demonstrate the circular array: + +```python +class CircularArray: + def __init__(self, size): + self.size = size + self.array = [None] * size + self.front = -1 + self.rear = -1 + + def is_empty(self): + return self.front == -1 + + def is_full(self): + return (self.rear + 1) % self.size == self.front + + def enqueue(self, value): + if self.is_full(): + print("The circular array is full. Cannot enqueue.") + return + if self.front == -1: + self.front = 0 + self.rear = (self.rear + 1) % self.size + self.array[self.rear] = value + print(f"Enqueued: {value}") + + def dequeue(self): + if self.is_empty(): + print("The circular array is empty. Cannot dequeue.") + return None + value = self.array[self.front] + if self.front == self.rear: + self.front = -1 + self.rear = -1 + else: + self.front = (self.front + 1) % self.size + print(f"Dequeued: {value}") + return value + + def display(self): + if self.is_empty(): + print("The circular array is empty.") + return + index = self.front + print("Circular Array Elements: ", end="") + while True: + print(self.array[index], end=" ") + if index == self.rear: + break + index = (index + 1) % self.size + print() +``` +## Java Implementation + +```java +public class CircularArray { + private int[] array; + private int front; + private int rear; + private int size; + + public CircularArray(int size) { + this.size = size; + array = new int[size]; + front = -1; + rear = -1; + } + + public boolean isEmpty() { + return front == -1; + } + + public boolean isFull() { + return (rear + 1) % size == front; + } + + public void enqueue(int value) { + if (isFull()) { + System.out.println("The circular array is full. Cannot enqueue."); + return; + } + if (front == -1) { + front = 0; + } + rear = (rear + 1) % size; + array[rear] = value; + System.out.println("Enqueued: " + value); + } + + public int dequeue() { + if (isEmpty()) { + System.out.println("The circular array is empty. Cannot dequeue."); + return -1; + } + int value = array[front]; + if (front == rear) { + front = -1; + rear = -1; + } else { + front = (front + 1) % size; + } + System.out.println("Dequeued: " + value); + return value; + } + + public void display() { + if (isEmpty()) { + System.out.println("The circular array is empty."); + return; + } + System.out.print("Circular Array Elements: "); + int index = front; + while (true) { + System.out.print(array[index] + " "); + if (index == rear) { + break; + } + index = (index + 1) % size; + } + System.out.println(); + } + + public static void main(String[] args) { + CircularArray ca = new CircularArray(5); + ca.enqueue(10); + ca.enqueue(20); + ca.enqueue(30); + ca.display(); + ca.dequeue(); + ca.display(); + } +} +``` +### C++ Implementation + +```C++ +#include +using namespace std; + +class CircularArray { +private: + int *array; + int front, rear, size; + +public: + CircularArray(int s) { + size = s; + array = new int[size]; + front = -1; + rear = -1; + } + + ~CircularArray() { + delete[] array; + } + + bool isEmpty() { + return front == -1; + } + + bool isFull() { + return (rear + 1) % size == front; + } + + void enqueue(int value) { + if (isFull()) { + cout << "The circular array is full. Cannot enqueue." << endl; + return; + } + if (front == -1) { + front = 0; + } + rear = (rear + 1) % size; + array[rear] = value; + cout << "Enqueued: " << value << endl; + } + + int dequeue() { + if (isEmpty()) { + cout << "The circular array is empty. Cannot dequeue." << endl; + return -1; + } + int value = array[front]; + if (front == rear) { + front = -1; + rear = -1; + } else { + front = (front + 1) % size; + } + cout << "Dequeued: " << value << endl; + return value; + } + + void display() { + if (isEmpty()) { + cout << "The circular array is empty." << endl; + return; + } + cout << "Circular Array Elements: "; + int index = front; + while (true) { + cout << array[index] << " "; + if (index == rear) { + break; + } + index = (index + 1) % size; + } + cout << endl; + } +}; + +int main() { + CircularArray ca(5); + ca.enqueue(10); + ca.enqueue(20); + ca.enqueue(30); + ca.display(); + ca.dequeue(); + ca.display(); + return 0; +} + +``` +## Complexity Analysis +- **Time Complexity**: + - **Enqueue/Dequeue**: $O(1)$ for insertion and deletion. +- **Space Complexity**: $O(n)$, where $n$ is the fixed size of the circular array. + +## Potential Issues and Solutions +- **Overflow**: Can occur if elements are added without checking if the array is full. + - Solution: Implement the `is_full()` method to prevent enqueueing when the array is at capacity. +- **Underflow**: Attempting to dequeue from an empty array. + - Solution: Implement the `is_empty()` method to handle this gracefully. + From 484a790d37d5675c672c06b67d33bd1536639fd1 Mon Sep 17 00:00:00 2001 From: Richa Jaishwal Date: Wed, 6 Nov 2024 19:14:33 +0530 Subject: [PATCH 2/2] Updated ID --- docs/Circular_array/Introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Circular_array/Introduction.md b/docs/Circular_array/Introduction.md index 964487116..71f81af4f 100644 --- a/docs/Circular_array/Introduction.md +++ b/docs/Circular_array/Introduction.md @@ -1,5 +1,5 @@ --- -id: Circular Array introduction +id: circular-array-introduction sidebar_position: 1 title: Introduction of Circular sidebar_label: Introduction