queue


Data Structure: Queue Data Structure in C++

A Queue is a linear data structure that follows the First-In-First-Out (FIFO) principle. This means that the first element added to the queue will be the first one to be removed. Queues are used in various applications where you need to maintain the order of elements and process them in the sequence they were added.

Key Characteristics

Example 1: Basic Queue Implementation Using an Array

This example demonstrates a basic implementation of a Queue using a circular array.

#include <iostream>
#include <stdexcept>

class Queue {
private:
    int* arr;
    int front;
    int rear;
    int capacity;
    int count;

public:
    Queue(int size) : capacity(size), front(0), rear(-1), count(0) {
        arr = new int[size];
    }

    ~Queue() {
        delete[] arr;
    }

    void enqueue(int x) {
        if (isFull()) {
            throw std::runtime_error("Queue is full");
        }
        rear = (rear + 1) % capacity;
        arr[rear] = x;
        count++;
    }

    int dequeue() {
        if (isEmpty()) {
            throw std::runtime_error("Queue is empty");
        }
        int x = arr[front];
        front = (front + 1) % capacity;
        count--;
        return x;
    }

    int peek() const {
        if (isEmpty()) {
            throw std::runtime_error("Queue is empty");
        }
        return arr[front];
    }

    int size() const {
        return count;
    }

    bool isEmpty() const {
        return (size() == 0);
    }

    bool isFull() const {
        return (size() == capacity);
    }
};

int main() {
    Queue q(5);

    q.enqueue(1);
    q.enqueue(2);
    q.enqueue(3);

    std::cout << "Front element is: " << q.peek() << std::endl;
    std::cout << "Queue size is: " << q.size() << std::endl;

    std::cout << "Dequeuing: " << q.dequeue() << std::endl;
    std::cout << "Dequeuing: " << q.dequeue() << std::endl;

    q.enqueue(4);
    q.enqueue(5);
    q.enqueue(6);

    std::cout << "Queue size is: " << q.size() << std::endl;

    try {
        q.enqueue(7);
    } catch (const std::exception& e) {
        std::cout << e.what() << std::endl;
    }

    while (!q.isEmpty()) {
        std::cout << "Dequeuing: " << q.dequeue() << std::endl;
    }

    try {
        q.dequeue();
    } catch (const std::exception& e) {
        std::cout << e.what() << std::endl;
    }

    return 0;
}

Explanation

Example 2: Queue Implementation Using std::queue for Task Scheduling

This example shows how to use the C++ Standard Library's std::queue to implement a simple task scheduler.

#include <iostream>
#include <queue>
#include <string>
#include <chrono>
#include <thread>

class Task {
public:
    std::string name;
    int priority;

    Task(const std::string& n, int p) : name(n), priority(p) {}

    void execute() const {
        std::cout << "Executing task: " << name << " (Priority: " << priority << ")" << std::endl;
        // Simulate task execution
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
};

class TaskScheduler {
private:
    std::queue<Task> taskQueue;

public:
    void addTask(const Task& task) {
        taskQueue.push(task);
    }

    void executeTasks() {
        while (!taskQueue.empty()) {
            Task currentTask = taskQueue.front();
            taskQueue.pop();
            currentTask.execute();
        }
    }

    bool hasTasks() const {
        return !taskQueue.empty();
    }

    int taskCount() const {
        return taskQueue.size();
    }
};

int main() {
    TaskScheduler scheduler;

    scheduler.addTask(Task("Read file", 2));
    scheduler.addTask(Task("Process data", 1));
    scheduler.addTask(Task("Write results", 3));
    scheduler.addTask(Task("Send notification", 4));

    std::cout << "Tasks in queue: " << scheduler.taskCount() << std::endl;

    std::cout << "Executing tasks:" << std::endl;
    scheduler.executeTasks();

    std::cout << "All tasks completed." << std::endl;

    return 0;
}

Explanation

Additional Considerations

  1. Priority Queues: For more complex scheduling needs, consider using a priority queue where tasks are ordered by priority rather than insertion order.

  2. Thread Safety: When using queues in multi-threaded environments, ensure proper synchronization to avoid race conditions.

  3. Bounded vs. Unbounded Queues: The first example shows a bounded queue (fixed capacity), while the second uses an unbounded queue. Choose based on your application's needs.

  4. Deque (Double-Ended Queue): For more flexibility, consider using a deque that allows insertion and deletion at both ends.

  5. Applications: Queues are widely used in:

  6. Breadth-First Search algorithms in graph theory
  7. CPU scheduling in operating systems
  8. Handling of interrupts in real-time systems
  9. Buffering in I/O operations

Summary

Queues are fundamental data structures that provide a simple yet powerful way to manage data in a First-In-First-Out manner. They are essential in many areas of computer science and software engineering.

In this guide, we explored two implementations of Queues:

  1. A basic Queue implementation using a circular array, demonstrating the core concepts and operations of a queue data structure.
  2. A task scheduler using std::queue, showing a practical application of queues in managing and executing tasks.

These examples highlight the versatility of queues in handling sequential data and their efficiency in maintaining order. The first example provides a low-level understanding of queue operations, while the second demonstrates how queues can be applied in real-world scenarios like task scheduling.

Queues are particularly relevant to your interests in scientific computing and artificial intelligence. In scientific computing, they can be used for managing computational tasks or simulations. In AI, queues are often used in algorithms like breadth-first search, which is fundamental in many AI search and optimization problems.

For further exploration, you might consider: - Implementing a priority queue for more complex scheduling needs - Exploring how queues are used in specific AI algorithms, such as in tree or graph traversals - Investigating the use of queues in parallel computing or distributed systems - Applying queue-based algorithms to specific problems in your scientific computing or AI research

Understanding and effectively using queues can significantly enhance your ability to design efficient algorithms and systems in both scientific computing and AI applications.

Related

Previous Page | Course Schedule | Course Content