Skip to content

Commit ca2677f

Browse files
feat: Add comprehensive Queue data structure (#284)
1 parent 91ea60e commit ca2677f

File tree

2 files changed

+295
-0
lines changed

2 files changed

+295
-0
lines changed

DIRECTORY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444

4545
## Data Structures
4646
* [Binary Search Tree](https://github.com/TheAlgorithms/R/blob/HEAD/data_structures/binary_search_tree.r)
47+
* Queue
48+
* [Queue Operations](https://github.com/TheAlgorithms/R/blob/HEAD/data_structures/Queue/queue_operations.r)
4749

4850
## Dynamic Programming
4951
* 0
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
# Queue Data Structure Implementation in R
2+
#
3+
# A queue is a linear data structure that follows the First In First Out (FIFO) principle.
4+
# Elements are added at the rear (enqueue) and removed from the front (dequeue).
5+
#
6+
# Time Complexities:
7+
# - Enqueue: O(1) - adding element to rear
8+
# - Dequeue: O(1) - removing element from front
9+
# - Peek/Front: O(1) - viewing front element
10+
# - Size: O(1) - getting queue size
11+
# - IsEmpty: O(1) - checking if queue is empty
12+
#
13+
# Space Complexity: O(n) where n is number of elements
14+
#
15+
# Applications:
16+
# - CPU scheduling and process management
17+
# - Breadth-First Search (BFS) in graphs
18+
# - Handling requests in web servers
19+
# - Print queue management
20+
# - Level order traversal in trees
21+
# - Buffer for data streams
22+
23+
# Define Queue class using Reference Classes
24+
Queue <- setRefClass("Queue",
25+
fields = list(
26+
items = "list",
27+
front_index = "numeric",
28+
rear_index = "numeric",
29+
max_size = "numeric"
30+
),
31+
methods = list(
32+
initialize = function(max_size = Inf) {
33+
"Initialize an empty queue with optional maximum size"
34+
.self$items <- list()
35+
.self$front_index <- 1
36+
.self$rear_index <- 0
37+
.self$max_size <- max_size
38+
cat("Queue initialized with max size:", ifelse(is.infinite(max_size), "unlimited", max_size), "\n")
39+
},
40+
41+
enqueue = function(item) {
42+
"Add an element to the rear of the queue"
43+
if (.self$size() >= .self$max_size) {
44+
stop("Queue overflow: Cannot add more elements. Max size reached: ", .self$max_size)
45+
}
46+
47+
.self$rear_index <- .self$rear_index + 1
48+
.self$items[[.self$rear_index]] <- item
49+
cat("Enqueued:", item, "| Size:", .self$size(), "\n")
50+
},
51+
52+
dequeue = function() {
53+
"Remove and return the front element from the queue"
54+
if (.self$is_empty()) {
55+
stop("Queue underflow: Cannot dequeue from empty queue")
56+
}
57+
58+
item <- .self$items[[.self$front_index]]
59+
.self$items[[.self$front_index]] <- NULL
60+
.self$front_index <- .self$front_index + 1
61+
62+
# Reset indices when queue becomes empty to optimize memory
63+
if (.self$is_empty()) {
64+
.self$front_index <- 1
65+
.self$rear_index <- 0
66+
.self$items <- list()
67+
}
68+
69+
cat("Dequeued:", item, "| Size:", .self$size(), "\n")
70+
return(item)
71+
},
72+
73+
front = function() {
74+
"Return the front element without removing it"
75+
if (.self$is_empty()) {
76+
stop("Queue is empty: No front element")
77+
}
78+
return(.self$items[[.self$front_index]])
79+
},
80+
81+
rear = function() {
82+
"Return the rear element without removing it"
83+
if (.self$is_empty()) {
84+
stop("Queue is empty: No rear element")
85+
}
86+
return(.self$items[[.self$rear_index]])
87+
},
88+
89+
is_empty = function() {
90+
"Check if the queue is empty"
91+
return(.self$rear_index < .self$front_index)
92+
},
93+
94+
is_full = function() {
95+
"Check if the queue is full (only applicable for bounded queues)"
96+
return(.self$size() >= .self$max_size)
97+
},
98+
99+
size = function() {
100+
"Return the number of elements in the queue"
101+
if (.self$is_empty()) return(0)
102+
return(.self$rear_index - .self$front_index + 1)
103+
},
104+
105+
clear = function() {
106+
"Remove all elements from the queue"
107+
.self$items <- list()
108+
.self$front_index <- 1
109+
.self$rear_index <- 0
110+
cat("Queue cleared\n")
111+
},
112+
113+
display = function() {
114+
"Display all elements in the queue from front to rear"
115+
if (.self$is_empty()) {
116+
cat("Queue is empty: []\n")
117+
return()
118+
}
119+
120+
elements <- character(0)
121+
for (i in .self$front_index:.self$rear_index) {
122+
if (i <= length(.self$items) && !is.null(.self$items[[i]])) {
123+
elements <- c(elements, as.character(.self$items[[i]]))
124+
}
125+
}
126+
cat("Queue: [", paste(elements, collapse = " <- "), "] (front <- rear)\n")
127+
},
128+
129+
to_vector = function() {
130+
"Convert queue to vector (front to rear order)"
131+
if (.self$is_empty()) return(c())
132+
133+
result <- c()
134+
for (i in .self$front_index:.self$rear_index) {
135+
result <- c(result, .self$items[[i]])
136+
}
137+
return(result)
138+
},
139+
140+
search = function(item) {
141+
"Search for an item in the queue and return its position from front (1-indexed)"
142+
if (.self$is_empty()) return(-1)
143+
144+
for (i in .self$front_index:.self$rear_index) {
145+
if (identical(.self$items[[i]], item)) {
146+
return(i - .self$front_index + 1)
147+
}
148+
}
149+
return(-1) # Item not found
150+
}
151+
)
152+
)
153+
154+
# Utility function to demonstrate queue operations
155+
demonstrate_queue_operations <- function() {
156+
cat("\n=== Queue Data Structure Demonstration ===\n\n")
157+
158+
# Create a queue with maximum size of 5
159+
q <- Queue$new(max_size = 5)
160+
161+
cat("\n1. Basic Enqueue Operations:\n")
162+
q$enqueue("A")
163+
q$enqueue("B")
164+
q$enqueue("C")
165+
q$display()
166+
167+
cat("\n2. Queue Status:\n")
168+
cat("Size:", q$size(), "\n")
169+
cat("Is Empty:", q$is_empty(), "\n")
170+
cat("Is Full:", q$is_full(), "\n")
171+
cat("Front element:", q$front(), "\n")
172+
cat("Rear element:", q$rear(), "\n")
173+
174+
cat("\n3. Dequeue Operations:\n")
175+
q$dequeue()
176+
q$display()
177+
q$dequeue()
178+
q$display()
179+
180+
cat("\n4. More Enqueue Operations:\n")
181+
q$enqueue("D")
182+
q$enqueue("E")
183+
q$enqueue("F")
184+
q$enqueue("G")
185+
q$display()
186+
187+
cat("\n5. Search Operations:\n")
188+
cat("Position of 'E':", q$search("E"), "\n")
189+
cat("Position of 'Z':", q$search("Z"), "\n")
190+
191+
cat("\n6. Queue to Vector:\n")
192+
vec <- q$to_vector()
193+
cat("As vector:", paste(vec, collapse = ", "), "\n")
194+
195+
cat("\n7. Testing Queue Overflow:\n")
196+
tryCatch({
197+
q$enqueue("H") # This should cause overflow
198+
}, error = function(e) {
199+
cat("Error caught:", e$message, "\n")
200+
})
201+
202+
cat("\n8. Clear Queue:\n")
203+
q$clear()
204+
q$display()
205+
206+
cat("\n9. Testing Queue Underflow:\n")
207+
tryCatch({
208+
q$dequeue() # This should cause underflow
209+
}, error = function(e) {
210+
cat("Error caught:", e$message, "\n")
211+
})
212+
}
213+
214+
# Priority Queue implementation (bonus)
215+
PriorityQueue <- setRefClass("PriorityQueue",
216+
fields = list(
217+
items = "list",
218+
priorities = "numeric"
219+
),
220+
methods = list(
221+
initialize = function() {
222+
"Initialize an empty priority queue"
223+
.self$items <- list()
224+
.self$priorities <- numeric(0)
225+
cat("Priority Queue initialized\n")
226+
},
227+
228+
enqueue = function(item, priority = 0) {
229+
"Add an element with priority (higher number = higher priority)"
230+
.self$items <- append(.self$items, list(item))
231+
.self$priorities <- append(.self$priorities, priority)
232+
cat("Enqueued:", item, "with priority:", priority, "\n")
233+
},
234+
235+
dequeue = function() {
236+
"Remove and return the highest priority element"
237+
if (length(.self$items) == 0) {
238+
stop("Priority queue is empty")
239+
}
240+
241+
max_priority_index <- which.max(.self$priorities)
242+
item <- .self$items[[max_priority_index]]
243+
priority <- .self$priorities[max_priority_index]
244+
245+
.self$items <- .self$items[-max_priority_index]
246+
.self$priorities <- .self$priorities[-max_priority_index]
247+
248+
cat("Dequeued:", item, "with priority:", priority, "\n")
249+
return(list(item = item, priority = priority))
250+
},
251+
252+
is_empty = function() {
253+
"Check if priority queue is empty"
254+
return(length(.self$items) == 0)
255+
},
256+
257+
size = function() {
258+
"Return number of elements"
259+
return(length(.self$items))
260+
},
261+
262+
display = function() {
263+
"Display all elements with their priorities"
264+
if (.self$is_empty()) {
265+
cat("Priority Queue is empty\n")
266+
return()
267+
}
268+
269+
cat("Priority Queue:\n")
270+
for (i in seq_along(.self$items)) {
271+
cat(" ", .self$items[[i]], "(priority:", .self$priorities[i], ")\n")
272+
}
273+
}
274+
)
275+
)
276+
277+
# Example usage and testing
278+
if (sys.nframe() == 0) {
279+
# Demonstrate basic queue operations
280+
demonstrate_queue_operations()
281+
282+
cat("\n\n=== Priority Queue Demonstration ===\n")
283+
pq <- PriorityQueue$new()
284+
pq$enqueue("Low priority task", 1)
285+
pq$enqueue("High priority task", 5)
286+
pq$enqueue("Medium priority task", 3)
287+
pq$display()
288+
289+
cat("\nDequeuing in priority order:\n")
290+
while (!pq$is_empty()) {
291+
pq$dequeue()
292+
}
293+
}

0 commit comments

Comments
 (0)