-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPracticalStacks.js
More file actions
153 lines (124 loc) · 3.91 KB
/
PracticalStacks.js
File metadata and controls
153 lines (124 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
1. Function call stack:
In Node.js, a call stack is used to track the order of function calls.
Whenever a function is called, it is pushed onto the stack.
Once the function is done executing, it is popped off the stack.
This ensures that the program knows which function to return to after the current function has finished.
*/
function firstFunction() {
console.log('First function called');
secondFunction();
}
function secondFunction() {
console.log('Second function called');
thirdFunction();
}
function thirdFunction() {
console.log('Third function called');
}
firstFunction();
/*
2. Expression evaluation:
Stacks can be used to evaluate arithmetic expressions in postfix notation (also known as Reverse Polish Notation).
This can be useful when creating a calculator program or when evaluating expressions in a custom language interpreter.
*/
function evaluatePostfixExpression(expression) {
const stack = [];
const operators = {
'+': (a, b) => a + b,
'-': (a, b) => a - b,
'*': (a, b) => a * b,
'/': (a, b) => a / b,
};
expression.split(' ').forEach((token) => {
if (token in operators) {
const b = stack.pop();
const a = stack.pop();
stack.push(operators[token](a, b));
} else {
stack.push(parseFloat(token));
}
});
return stack.pop();
}
console.log(evaluatePostfixExpression('3 4 + 5 *')); // (3 + 4) * 5 = 35
/*
3. Reversing a string:
Stacks can be used to reverse a string by pushing each character onto a stack and then popping them off in reverse order.
*/
function reverseString(str) {
const stack = [];
for (const char of str) {
stack.push(char);
}
let reversed = '';
while (stack.length > 0) {
reversed += stack.pop();
}
return reversed;
}
console.log(reverseString('hello')); // 'olleh'
/*
4. Balancing parentheses:
Stacks can be used to check if a string with parentheses, brackets, and braces is balanced.
This can be useful when validating code or user input.
*/
function isBalanced(input) {
const stack = [];
const pairs = {
'(': ')',
'[': ']',
'{': '}',
};
for (const char of input) {
if (char in pairs) {
stack.push(char);
} else if (Object.values(pairs).includes(char)) {
if (stack.length === 0 || pairs[stack.pop()] !== char) {
return false;
}
}
}
return stack.length === 0;
}
console.log(isBalanced('{[()]}')); // true
console.log(isBalanced('{[(])}')); // false
/*
Undo/Redo functionality:
Stacks can be used to implement undo and redo functionality in an application by keeping track of user actions on two separate stacks.
*/
class History {
constructor() {
this.undoStack = [];
this.redoStack = [];
}
// Add a new action to the undo stack and clear the redo stack
addAction(action) {
this.undoStack.push(action);
this.redoStack = [];
}
// Undo the last action by moving it from the undo stack to the redo stack
undo() {
if (this.undoStack.length === 0) return;
const action = this.undoStack.pop();
this.redoStack.push(action);
console.log(`Undo: ${action}`);
}
// Redo the last undone action by moving it back from the redo stack to the undo stack
redo() {
if (this.redoStack.length === 0) return;
const action = this.redoStack.pop();
this.undoStack.push(action);
console.log(`Redo: ${action}`);
}
}
// Example usage
const history = new History();
history.addAction('Type A');
history.addAction('Type B');
history.addAction('Type C');
history.undo(); // Undo: Type C
history.undo(); // Undo: Type B
history.redo(); // Redo: Type B
history.addAction('Type D'); // Performing a new action resets the redo history
history.redo(); // No action, as redo history has been reset