diff --git a/DIRECTORY.md b/DIRECTORY.md index a7a1e1b5..f1f26465 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -41,6 +41,8 @@ ## Data Structures * [Binary Search Tree](https://github.com/TheAlgorithms/R/blob/HEAD/data_structures/binary_search_tree.r) + * Queue + * [Queue Operations](https://github.com/TheAlgorithms/R/blob/HEAD/data_structures/Queue/queue_operations.r) ## Dynamic Programming * 0 diff --git a/data_structures/Queue/queue_operations.r b/data_structures/Queue/queue_operations.r new file mode 100644 index 00000000..cf0b36f3 --- /dev/null +++ b/data_structures/Queue/queue_operations.r @@ -0,0 +1,293 @@ +# Queue Data Structure Implementation in R +# +# A queue is a linear data structure that follows the First In First Out (FIFO) principle. +# Elements are added at the rear (enqueue) and removed from the front (dequeue). +# +# Time Complexities: +# - Enqueue: O(1) - adding element to rear +# - Dequeue: O(1) - removing element from front +# - Peek/Front: O(1) - viewing front element +# - Size: O(1) - getting queue size +# - IsEmpty: O(1) - checking if queue is empty +# +# Space Complexity: O(n) where n is number of elements +# +# Applications: +# - CPU scheduling and process management +# - Breadth-First Search (BFS) in graphs +# - Handling requests in web servers +# - Print queue management +# - Level order traversal in trees +# - Buffer for data streams + +# Define Queue class using Reference Classes +Queue <- setRefClass("Queue", + fields = list( + items = "list", + front_index = "numeric", + rear_index = "numeric", + max_size = "numeric" + ), + methods = list( + initialize = function(max_size = Inf) { + "Initialize an empty queue with optional maximum size" + .self$items <- list() + .self$front_index <- 1 + .self$rear_index <- 0 + .self$max_size <- max_size + cat("Queue initialized with max size:", ifelse(is.infinite(max_size), "unlimited", max_size), "\n") + }, + + enqueue = function(item) { + "Add an element to the rear of the queue" + if (.self$size() >= .self$max_size) { + stop("Queue overflow: Cannot add more elements. Max size reached: ", .self$max_size) + } + + .self$rear_index <- .self$rear_index + 1 + .self$items[[.self$rear_index]] <- item + cat("Enqueued:", item, "| Size:", .self$size(), "\n") + }, + + dequeue = function() { + "Remove and return the front element from the queue" + if (.self$is_empty()) { + stop("Queue underflow: Cannot dequeue from empty queue") + } + + item <- .self$items[[.self$front_index]] + .self$items[[.self$front_index]] <- NULL + .self$front_index <- .self$front_index + 1 + + # Reset indices when queue becomes empty to optimize memory + if (.self$is_empty()) { + .self$front_index <- 1 + .self$rear_index <- 0 + .self$items <- list() + } + + cat("Dequeued:", item, "| Size:", .self$size(), "\n") + return(item) + }, + + front = function() { + "Return the front element without removing it" + if (.self$is_empty()) { + stop("Queue is empty: No front element") + } + return(.self$items[[.self$front_index]]) + }, + + rear = function() { + "Return the rear element without removing it" + if (.self$is_empty()) { + stop("Queue is empty: No rear element") + } + return(.self$items[[.self$rear_index]]) + }, + + is_empty = function() { + "Check if the queue is empty" + return(.self$rear_index < .self$front_index) + }, + + is_full = function() { + "Check if the queue is full (only applicable for bounded queues)" + return(.self$size() >= .self$max_size) + }, + + size = function() { + "Return the number of elements in the queue" + if (.self$is_empty()) return(0) + return(.self$rear_index - .self$front_index + 1) + }, + + clear = function() { + "Remove all elements from the queue" + .self$items <- list() + .self$front_index <- 1 + .self$rear_index <- 0 + cat("Queue cleared\n") + }, + + display = function() { + "Display all elements in the queue from front to rear" + if (.self$is_empty()) { + cat("Queue is empty: []\n") + return() + } + + elements <- character(0) + for (i in .self$front_index:.self$rear_index) { + if (i <= length(.self$items) && !is.null(.self$items[[i]])) { + elements <- c(elements, as.character(.self$items[[i]])) + } + } + cat("Queue: [", paste(elements, collapse = " <- "), "] (front <- rear)\n") + }, + + to_vector = function() { + "Convert queue to vector (front to rear order)" + if (.self$is_empty()) return(c()) + + result <- c() + for (i in .self$front_index:.self$rear_index) { + result <- c(result, .self$items[[i]]) + } + return(result) + }, + + search = function(item) { + "Search for an item in the queue and return its position from front (1-indexed)" + if (.self$is_empty()) return(-1) + + for (i in .self$front_index:.self$rear_index) { + if (identical(.self$items[[i]], item)) { + return(i - .self$front_index + 1) + } + } + return(-1) # Item not found + } + ) +) + +# Utility function to demonstrate queue operations +demonstrate_queue_operations <- function() { + cat("\n=== Queue Data Structure Demonstration ===\n\n") + + # Create a queue with maximum size of 5 + q <- Queue$new(max_size = 5) + + cat("\n1. Basic Enqueue Operations:\n") + q$enqueue("A") + q$enqueue("B") + q$enqueue("C") + q$display() + + cat("\n2. Queue Status:\n") + cat("Size:", q$size(), "\n") + cat("Is Empty:", q$is_empty(), "\n") + cat("Is Full:", q$is_full(), "\n") + cat("Front element:", q$front(), "\n") + cat("Rear element:", q$rear(), "\n") + + cat("\n3. Dequeue Operations:\n") + q$dequeue() + q$display() + q$dequeue() + q$display() + + cat("\n4. More Enqueue Operations:\n") + q$enqueue("D") + q$enqueue("E") + q$enqueue("F") + q$enqueue("G") + q$display() + + cat("\n5. Search Operations:\n") + cat("Position of 'E':", q$search("E"), "\n") + cat("Position of 'Z':", q$search("Z"), "\n") + + cat("\n6. Queue to Vector:\n") + vec <- q$to_vector() + cat("As vector:", paste(vec, collapse = ", "), "\n") + + cat("\n7. Testing Queue Overflow:\n") + tryCatch({ + q$enqueue("H") # This should cause overflow + }, error = function(e) { + cat("Error caught:", e$message, "\n") + }) + + cat("\n8. Clear Queue:\n") + q$clear() + q$display() + + cat("\n9. Testing Queue Underflow:\n") + tryCatch({ + q$dequeue() # This should cause underflow + }, error = function(e) { + cat("Error caught:", e$message, "\n") + }) +} + +# Priority Queue implementation (bonus) +PriorityQueue <- setRefClass("PriorityQueue", + fields = list( + items = "list", + priorities = "numeric" + ), + methods = list( + initialize = function() { + "Initialize an empty priority queue" + .self$items <- list() + .self$priorities <- numeric(0) + cat("Priority Queue initialized\n") + }, + + enqueue = function(item, priority = 0) { + "Add an element with priority (higher number = higher priority)" + .self$items <- append(.self$items, list(item)) + .self$priorities <- append(.self$priorities, priority) + cat("Enqueued:", item, "with priority:", priority, "\n") + }, + + dequeue = function() { + "Remove and return the highest priority element" + if (length(.self$items) == 0) { + stop("Priority queue is empty") + } + + max_priority_index <- which.max(.self$priorities) + item <- .self$items[[max_priority_index]] + priority <- .self$priorities[max_priority_index] + + .self$items <- .self$items[-max_priority_index] + .self$priorities <- .self$priorities[-max_priority_index] + + cat("Dequeued:", item, "with priority:", priority, "\n") + return(list(item = item, priority = priority)) + }, + + is_empty = function() { + "Check if priority queue is empty" + return(length(.self$items) == 0) + }, + + size = function() { + "Return number of elements" + return(length(.self$items)) + }, + + display = function() { + "Display all elements with their priorities" + if (.self$is_empty()) { + cat("Priority Queue is empty\n") + return() + } + + cat("Priority Queue:\n") + for (i in seq_along(.self$items)) { + cat(" ", .self$items[[i]], "(priority:", .self$priorities[i], ")\n") + } + } + ) +) + +# Example usage and testing +if (sys.nframe() == 0) { + # Demonstrate basic queue operations + demonstrate_queue_operations() + + cat("\n\n=== Priority Queue Demonstration ===\n") + pq <- PriorityQueue$new() + pq$enqueue("Low priority task", 1) + pq$enqueue("High priority task", 5) + pq$enqueue("Medium priority task", 3) + pq$display() + + cat("\nDequeuing in priority order:\n") + while (!pq$is_empty()) { + pq$dequeue() + } +} \ No newline at end of file