Skip to content

Commit 54a20b4

Browse files
Rework on Stack Array Data Structure (TheAlgorithms#2683)
* ref: rework on stack array data structure - The `Stack` class is placed within the `data_structures` namespace - The destructor is added to the Stack class to ensure memory deallocation - Comments are added to the member functions to describe their purpose - The self-test function is provided, which demonstrates the usage of the Stack class * chore(docs): add `namespace` docstring * chore: add `std::out_of_range` exception and test cases when stack is empty * ref: add `full` and `empty` methods * ref: improve stack array implementation - Use TOS instead of stack index - Add tests for overflow and underflow * fix: remove comparision to true from asserts * chore: remove `stack.hpp` * fix: revert * Update data_structures/stack_using_array.cpp * docs: add namespace comment * chore: remove redundant line in docstring of `empty` method --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com>
1 parent fe41cf4 commit 54a20b4

File tree

1 file changed

+166
-49
lines changed

1 file changed

+166
-49
lines changed

data_structures/stack_using_array.cpp

Lines changed: 166 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,179 @@
1-
#include <iostream>
1+
#include <cassert> /// For std::assert
2+
#include <iostream> /// For std::cout
3+
#include <memory> /// For std::unique_ptr
4+
#include <stdexcept> /// For std::out_of_range
25

3-
int *stack;
4-
int stack_idx = 0, stack_size;
6+
/**
7+
* @namespace
8+
* @brief data_structures
9+
*/
10+
namespace data_structures {
11+
/**
12+
* @brief Class representation of a stack
13+
* @tparam T The type of the elements in the stack
14+
*/
15+
template <typename T>
16+
class Stack {
17+
private:
18+
std::unique_ptr<T[]> stack; ///< Smart pointer to the stack array
19+
int stackSize; ///< Maximum size of the stack
20+
int stackIndex; ///< Index pointing to the top element of the stack
521

6-
void push(int x) {
7-
if (stack_idx == stack_size) {
8-
std::cout << "\nOverflow";
9-
} else {
10-
stack[stack_idx++] = x;
22+
public:
23+
/**
24+
* @brief Constructs a new Stack object
25+
*
26+
* @param size Maximum size of the stack
27+
*/
28+
Stack(int size) : stackSize(size), stackIndex(-1), stack(new T[size]) {}
29+
30+
/**
31+
* @brief Checks if the stack is full
32+
*
33+
* @return true if the stack is full, false otherwise
34+
*/
35+
bool full() const { return stackIndex == stackSize - 1; }
36+
37+
/**
38+
* @brief Checks if the stack is empty
39+
* @return true if the stack is empty, false otherwise
40+
*/
41+
bool empty() const { return stackIndex == -1; }
42+
43+
/**
44+
* @brief Pushes an element onto the stack
45+
*
46+
* @param element Element to push onto the stack
47+
*/
48+
void push(T element) {
49+
if (full()) {
50+
throw std::out_of_range("Stack overflow");
51+
} else {
52+
stack[++stackIndex] = element;
53+
}
1154
}
12-
}
1355

14-
void pop() {
15-
if (stack_idx == 0) {
16-
std::cout << "\nUnderflow";
17-
} else {
18-
std::cout << "\n" << stack[--stack_idx] << " deleted";
56+
/**
57+
* @brief Pops an element from the stack
58+
*
59+
* @return The popped element
60+
* @throws std::out_of_range if the stack is empty
61+
*/
62+
T pop() {
63+
if (empty()) {
64+
throw std::out_of_range("Stack underflow");
65+
}
66+
return stack[stackIndex--];
67+
}
68+
69+
/**
70+
* @brief Displays all elements in the stack
71+
*/
72+
void show() const {
73+
for (int i = 0; i <= stackIndex; i++) {
74+
std::cout << stack[i] << "\n";
75+
}
1976
}
20-
}
2177

22-
void show() {
23-
for (int i = 0; i < stack_idx; i++) {
24-
std::cout << stack[i] << "\n";
78+
/**
79+
* @brief Displays the topmost element of the stack
80+
*
81+
* @return The topmost element of the stack
82+
* @throws std::out_of_range if the stack is empty
83+
*/
84+
T topmost() const {
85+
if (empty()) {
86+
throw std::out_of_range("Stack underflow");
87+
}
88+
return stack[stackIndex];
2589
}
26-
}
2790

28-
void topmost() { std::cout << "\nTopmost element: " << stack[stack_idx - 1]; }
29-
void bottom() { std::cout << "\nBottom element: " << stack[0]; } // If we need access to first element without using pop command
30-
int main() {
31-
std::cout << "\nEnter stack_size of stack : ";
32-
std::cin >> stack_size;
33-
stack = new int[stack_size];
34-
int ch, x;
35-
do {
36-
std::cout << "\n0. Exit";
37-
std::cout << "\n1. Push";
38-
std::cout << "\n2. Pop";
39-
std::cout << "\n3. Print";
40-
std::cout << "\n4. Print topmost element:";
41-
std::cout << "\n5. Print Bottom element:";
42-
std::cout << "\nEnter Your Choice : ";
43-
std::cin >> ch;
44-
if (ch == 1) {
45-
std::cout << "\nInsert : ";
46-
std::cin >> x;
47-
push(x);
48-
} else if (ch == 2) {
49-
pop();
50-
} else if (ch == 3) {
51-
show();
52-
} else if (ch == 4) {
53-
topmost();
54-
} else if(ch == 5) {
55-
bottom();
91+
/**
92+
* @brief Displays the bottom element of the stack
93+
*
94+
* @return The bottom element of the stack
95+
* @throws std::out_of_range if the stack is empty
96+
*/
97+
T bottom() const {
98+
if (empty()) {
99+
throw std::out_of_range("Stack underflow");
56100
}
57-
} while (ch != 0);
101+
return stack[0];
102+
}
103+
};
104+
} // namespace data_structures
105+
106+
/**
107+
* @brief Self-test implementations
108+
* @returns void
109+
*/
110+
static void test() {
111+
data_structures::Stack<int> stack(5);
112+
113+
// Test empty and full operations
114+
assert(stack.empty());
115+
assert(!stack.full());
58116

59-
delete[] stack;
117+
// Test pushing elements and checking topmost
118+
stack.push(10);
119+
assert(stack.topmost() == 10);
60120

121+
stack.push(20);
122+
assert(stack.topmost() == 20);
123+
124+
stack.push(30);
125+
stack.push(40);
126+
stack.push(50);
127+
assert(stack.full());
128+
129+
// Test stack overflow
130+
try {
131+
stack.push(60);
132+
} catch (const std::out_of_range& e) {
133+
assert(std::string(e.what()) == "Stack overflow");
134+
}
135+
136+
// Test popping elements
137+
assert(stack.pop() == 50);
138+
assert(stack.pop() == 40);
139+
assert(stack.pop() == 30);
140+
141+
// Check topmost and bottom elements
142+
assert(stack.topmost() == 20);
143+
assert(stack.bottom() == 10);
144+
145+
assert(stack.pop() == 20);
146+
assert(stack.pop() == 10);
147+
148+
assert(stack.empty());
149+
assert(!stack.full());
150+
151+
// Test stack underflow
152+
try {
153+
stack.pop();
154+
} catch (const std::out_of_range& e) {
155+
assert(std::string(e.what()) == "Stack underflow");
156+
}
157+
158+
try {
159+
stack.topmost();
160+
} catch (const std::out_of_range& e) {
161+
assert(std::string(e.what()) == "Stack underflow");
162+
}
163+
164+
try {
165+
stack.bottom();
166+
} catch (const std::out_of_range& e) {
167+
assert(std::string(e.what()) == "Stack underflow");
168+
}
169+
}
170+
171+
/**
172+
* @brief Main function
173+
* @returns 0 on exit
174+
*/
175+
int main() {
176+
test(); // run self-test implementations
177+
std::cout << "All tests passed!" << std::endl;
61178
return 0;
62179
}

0 commit comments

Comments
 (0)