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(" \n 1. Basic Enqueue Operations:\n " )
162+ q $ enqueue(" A" )
163+ q $ enqueue(" B" )
164+ q $ enqueue(" C" )
165+ q $ display()
166+
167+ cat(" \n 2. 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(" \n 3. Dequeue Operations:\n " )
175+ q $ dequeue()
176+ q $ display()
177+ q $ dequeue()
178+ q $ display()
179+
180+ cat(" \n 4. 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(" \n 5. Search Operations:\n " )
188+ cat(" Position of 'E':" , q $ search(" E" ), " \n " )
189+ cat(" Position of 'Z':" , q $ search(" Z" ), " \n " )
190+
191+ cat(" \n 6. Queue to Vector:\n " )
192+ vec <- q $ to_vector()
193+ cat(" As vector:" , paste(vec , collapse = " , " ), " \n " )
194+
195+ cat(" \n 7. 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(" \n 8. Clear Queue:\n " )
203+ q $ clear()
204+ q $ display()
205+
206+ cat(" \n 9. 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(" \n Dequeuing in priority order:\n " )
290+ while (! pq $ is_empty()) {
291+ pq $ dequeue()
292+ }
293+ }
0 commit comments