Skip to content

Commit 13e812c

Browse files
Add comprehensive Stack data structure implementation
Features: - Complete Stack class with LIFO operations (push, pop, peek, search) - Expression evaluator for infix to postfix conversion and evaluation - Balanced parentheses checker for multiple bracket types - Function call stack simulator - Next Greater Element problem solver using stack - Stock span problem and largest rectangle in histogram algorithms - Circular array next greater element finder - Comprehensive test cases and step-by-step demonstrations Files added: - data_structures/Stack/stack_operations.r (400+ lines) - data_structures/Stack/next_greater_element.r (300+ lines) - Updated DIRECTORY.md with Stack section
1 parent f4b992a commit 13e812c

File tree

3 files changed

+816
-0
lines changed

3 files changed

+816
-0
lines changed

DIRECTORY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141

4242
## Data Structures
4343
* [Binary Search Tree](https://github.com/TheAlgorithms/R/blob/HEAD/data_structures/binary_search_tree.r)
44+
* Stack
45+
* [Next Greater Element](https://github.com/TheAlgorithms/R/blob/HEAD/data_structures/Stack/next_greater_element.r)
46+
* [Stack Operations](https://github.com/TheAlgorithms/R/blob/HEAD/data_structures/Stack/stack_operations.r)
4447

4548
## Dynamic Programming
4649
* 0
Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
# Next Greater Element Problem - Stack Implementation
2+
#
3+
# Problem Statement:
4+
# Given an array of integers, for each element find the next greater element to its right.
5+
# The next greater element for an element x is the first greater element on the right side of x.
6+
# If no greater element exists, return -1 for that element.
7+
#
8+
# Examples:
9+
# Input: [4, 5, 2, 25]
10+
# Output: [5, 25, 25, -1]
11+
# Explanation:
12+
# - For 4, next greater is 5
13+
# - For 5, next greater is 25
14+
# - For 2, next greater is 25
15+
# - For 25, no greater element exists
16+
#
17+
# Input: [13, 7, 6, 12]
18+
# Output: [-1, 12, 12, -1]
19+
#
20+
# Input: [1, 3, 2, 4]
21+
# Output: [3, 4, 4, -1]
22+
#
23+
# Algorithm: Stack-based O(n) solution
24+
# Time Complexity: O(n) - each element is pushed and popped at most once
25+
# Space Complexity: O(n) - for the stack in worst case (decreasing sequence)
26+
27+
# Simple Stack implementation for algorithm use
28+
AlgorithmStack <- setRefClass("AlgorithmStack",
29+
fields = list(
30+
items = "list",
31+
top_idx = "numeric"
32+
),
33+
methods = list(
34+
initialize = function() {
35+
.self$items <- list()
36+
.self$top_idx <- 0
37+
},
38+
39+
push = function(item) {
40+
.self$top_idx <- .self$top_idx + 1
41+
.self$items[[.self$top_idx]] <- item
42+
},
43+
44+
pop = function() {
45+
if (.self$top_idx == 0) return(NULL)
46+
item <- .self$items[[.self$top_idx]]
47+
.self$top_idx <- .self$top_idx - 1
48+
return(item)
49+
},
50+
51+
peek = function() {
52+
if (.self$top_idx == 0) return(NULL)
53+
return(.self$items[[.self$top_idx]])
54+
},
55+
56+
is_empty = function() {
57+
return(.self$top_idx == 0)
58+
},
59+
60+
size = function() {
61+
return(.self$top_idx)
62+
}
63+
)
64+
)
65+
66+
# Main function to find next greater elements
67+
next_greater_element <- function(arr) {
68+
"Find next greater element for each element in array using stack"
69+
if (length(arr) == 0) return(c())
70+
71+
n <- length(arr)
72+
result <- rep(-1, n) # Initialize all with -1
73+
stack <- AlgorithmStack$new()
74+
75+
# Process each element from left to right
76+
for (i in 1:n) {
77+
# While stack is not empty and current element is greater than
78+
# the element at index stored at top of stack
79+
while (!stack$is_empty() && arr[i] > arr[stack$peek()]) {
80+
index <- stack$pop()
81+
result[index] <- arr[i]
82+
}
83+
84+
# Push current element's index to stack
85+
stack$push(i)
86+
}
87+
88+
return(result)
89+
}
90+
91+
# Enhanced version with step-by-step visualization
92+
next_greater_element_with_steps <- function(arr) {
93+
"Find next greater elements with detailed step-by-step visualization"
94+
if (length(arr) == 0) return(list(result = c(), steps = list()))
95+
96+
n <- length(arr)
97+
result <- rep(-1, n)
98+
stack <- AlgorithmStack$new()
99+
steps <- list()
100+
101+
# Initial state
102+
steps[[1]] <- list(
103+
step = 0,
104+
current_element = "Start",
105+
array = arr,
106+
stack_contents = c(),
107+
result = result,
108+
description = "Initial state"
109+
)
110+
111+
for (i in 1:n) {
112+
step_description <- paste("Processing element", arr[i], "at index", i)
113+
114+
# Pop elements and update result
115+
popped_elements <- c()
116+
while (!stack$is_empty() && arr[i] > arr[stack$peek()]) {
117+
index <- stack$pop()
118+
result[index] <- arr[i]
119+
popped_elements <- c(popped_elements, index)
120+
}
121+
122+
if (length(popped_elements) > 0) {
123+
step_description <- paste(step_description, "| Found NGE for indices:", paste(popped_elements, collapse = ", "))
124+
}
125+
126+
# Push current index
127+
stack$push(i)
128+
129+
# Get current stack contents for visualization
130+
stack_contents <- c()
131+
if (!stack$is_empty()) {
132+
for (j in 1:stack$size()) {
133+
if (j <= length(stack$items)) {
134+
stack_contents <- c(stack_contents, stack$items[[j]])
135+
}
136+
}
137+
}
138+
139+
# Record step
140+
steps[[i + 1]] <- list(
141+
step = i,
142+
current_element = arr[i],
143+
array = arr,
144+
stack_contents = stack_contents,
145+
result = result,
146+
description = step_description
147+
)
148+
}
149+
150+
return(list(result = result, steps = steps))
151+
}
152+
153+
# Helper function to print array nicely
154+
print_array <- function(arr, title = "Array") {
155+
cat(title, ": [", paste(arr, collapse = ", "), "]\n")
156+
}
157+
158+
# Helper function to print step visualization
159+
print_step <- function(step_info) {
160+
cat("\nStep", step_info$step, ":", step_info$description, "\n")
161+
cat("Current element:", step_info$current_element, "\n")
162+
print_array(step_info$array, "Input")
163+
164+
if (length(step_info$stack_contents) > 0) {
165+
stack_values <- sapply(step_info$stack_contents, function(idx) paste0(step_info$array[idx], "(", idx, ")"))
166+
cat("Stack (indices): [", paste(stack_values, collapse = ", "), "]\n")
167+
} else {
168+
cat("Stack: [empty]\n")
169+
}
170+
171+
print_array(step_info$result, "Result so far")
172+
}
173+
174+
# Next Greater Element to the Right for Circular Array
175+
next_greater_element_circular <- function(arr) {
176+
"Find next greater elements in circular array (wrapping around)"
177+
if (length(arr) == 0) return(c())
178+
179+
n <- length(arr)
180+
result <- rep(-1, n)
181+
stack <- AlgorithmStack$new()
182+
183+
# Process the array twice to handle circular nature
184+
for (i in 1:(2 * n)) {
185+
current_index <- ((i - 1) %% n) + 1 # Convert to 1-based circular index
186+
187+
while (!stack$is_empty() && arr[current_index] > arr[stack$peek()]) {
188+
index <- stack$pop()
189+
if (result[index] == -1) { # Only update if not already found
190+
result[index] <- arr[current_index]
191+
}
192+
}
193+
194+
if (i <= n) { # Only push indices in first pass
195+
stack$push(current_index)
196+
}
197+
}
198+
199+
return(result)
200+
}
201+
202+
# Previous Greater Element (using stack)
203+
previous_greater_element <- function(arr) {
204+
"Find previous greater element for each element"
205+
if (length(arr) == 0) return(c())
206+
207+
n <- length(arr)
208+
result <- rep(-1, n)
209+
stack <- AlgorithmStack$new()
210+
211+
# Process from left to right
212+
for (i in 1:n) {
213+
# Remove smaller or equal elements
214+
while (!stack$is_empty() && arr[stack$peek()] <= arr[i]) {
215+
stack$pop()
216+
}
217+
218+
# If stack is not empty, top element is previous greater
219+
if (!stack$is_empty()) {
220+
result[i] <- arr[stack$peek()]
221+
}
222+
223+
stack$push(i)
224+
}
225+
226+
return(result)
227+
}
228+
229+
# Stock Span Problem using Stack
230+
stock_span <- function(prices) {
231+
"Calculate stock span for each day (consecutive previous days with price <= current day)"
232+
if (length(prices) == 0) return(c())
233+
234+
n <- length(prices)
235+
spans <- rep(1, n) # Initialize all spans to 1
236+
stack <- AlgorithmStack$new()
237+
238+
for (i in 1:n) {
239+
# Pop elements while stack is not empty and
240+
# price at stack top is less than or equal to current price
241+
while (!stack$is_empty() && prices[stack$peek()] <= prices[i]) {
242+
stack$pop()
243+
}
244+
245+
# If stack becomes empty, span is i (all previous days)
246+
# Otherwise, span is difference between current index and index at stack top
247+
spans[i] <- if (stack$is_empty()) i else (i - stack$peek())
248+
249+
# Push current index to stack
250+
stack$push(i)
251+
}
252+
253+
return(spans)
254+
}
255+
256+
# Largest Rectangle in Histogram using Stack
257+
largest_rectangle_histogram <- function(heights) {
258+
"Find the largest rectangle area in histogram using stack"
259+
if (length(heights) == 0) return(0)
260+
261+
n <- length(heights)
262+
stack <- AlgorithmStack$new()
263+
max_area <- 0
264+
265+
for (i in 1:n) {
266+
# While stack is not empty and current height is less than
267+
# height at stack top, calculate area with stack top as smallest bar
268+
while (!stack$is_empty() && heights[i] < heights[stack$peek()]) {
269+
height <- heights[stack$pop()]
270+
width <- if (stack$is_empty()) i - 1 else i - stack$peek() - 1
271+
area <- height * width
272+
max_area <- max(max_area, area)
273+
}
274+
stack$push(i)
275+
}
276+
277+
# Process remaining bars in stack
278+
while (!stack$is_empty()) {
279+
height <- heights[stack$pop()]
280+
width <- if (stack$is_empty()) n else n - stack$peek()
281+
area <- height * width
282+
max_area <- max(max_area, area)
283+
}
284+
285+
return(max_area)
286+
}
287+
288+
# Function to demonstrate all stack applications
289+
demonstrate_stack_applications <- function() {
290+
cat("=== Stack Applications - Problem Solving ===\n")
291+
292+
# Test Case 1: Next Greater Element
293+
cat("\n--- Next Greater Element Problem ---\n")
294+
test_arrays <- list(
295+
c(4, 5, 2, 25),
296+
c(13, 7, 6, 12),
297+
c(1, 3, 2, 4),
298+
c(5, 4, 3, 2, 1),
299+
c(1, 2, 3, 4, 5)
300+
)
301+
302+
for (i in seq_along(test_arrays)) {
303+
arr <- test_arrays[[i]]
304+
result <- next_greater_element(arr)
305+
cat("\nTest", i, ":\n")
306+
print_array(arr, "Input")
307+
print_array(result, "Next Greater")
308+
}
309+
310+
# Test Case 2: Circular Array
311+
cat("\n--- Next Greater Element (Circular Array) ---\n")
312+
circular_test <- c(1, 2, 1)
313+
print_array(circular_test, "Input")
314+
circular_result <- next_greater_element_circular(circular_test)
315+
print_array(circular_result, "Next Greater (Circular)")
316+
317+
# Test Case 3: Previous Greater Element
318+
cat("\n--- Previous Greater Element ---\n")
319+
prev_test <- c(4, 5, 2, 25, 7, 8)
320+
print_array(prev_test, "Input")
321+
prev_result <- previous_greater_element(prev_test)
322+
print_array(prev_result, "Previous Greater")
323+
324+
# Test Case 4: Stock Span Problem
325+
cat("\n--- Stock Span Problem ---\n")
326+
stock_prices <- c(100, 80, 60, 70, 60, 75, 85)
327+
print_array(stock_prices, "Stock Prices")
328+
span_result <- stock_span(stock_prices)
329+
print_array(span_result, "Stock Spans")
330+
cat("Explanation: Span[i] = number of consecutive days (including current) with price <= price[i]\n")
331+
332+
# Test Case 5: Largest Rectangle in Histogram
333+
cat("\n--- Largest Rectangle in Histogram ---\n")
334+
histogram_heights <- c(6, 2, 5, 4, 5, 1, 6)
335+
print_array(histogram_heights, "Histogram Heights")
336+
max_area <- largest_rectangle_histogram(histogram_heights)
337+
cat("Largest Rectangle Area:", max_area, "\n")
338+
}
339+
340+
# Detailed step-by-step demonstration
341+
demonstrate_detailed_steps <- function() {
342+
cat("\n\n=== Detailed Step-by-Step: Next Greater Element ===\n")
343+
344+
test_array <- c(4, 5, 2, 25)
345+
cat("\nSolving for array:", paste(test_array, collapse = ", "), "\n")
346+
cat("Algorithm: Use stack to store indices of elements for which NGE is not found yet\n")
347+
348+
solution <- next_greater_element_with_steps(test_array)
349+
350+
for (step in solution$steps) {
351+
print_step(step)
352+
}
353+
354+
cat("\nFinal Result:", paste(solution$result, collapse = ", "), "\n")
355+
cat("\nTime Complexity: O(n) - each element pushed and popped at most once\n")
356+
cat("Space Complexity: O(n) - for the stack in worst case\n")
357+
}
358+
359+
# Run demonstrations if script is executed directly
360+
if (sys.nframe() == 0) {
361+
demonstrate_stack_applications()
362+
demonstrate_detailed_steps()
363+
}

0 commit comments

Comments
 (0)