Skip to content

Commit 15e7872

Browse files
committed
adding stack data structure
1 parent 912813b commit 15e7872

File tree

4 files changed

+302
-0
lines changed

4 files changed

+302
-0
lines changed

stack-data-structure/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Stack
2+
In computer science, a **stack** is an abstract data type that serves
3+
as a collection of elements, with two principal operations:
4+
* **push**, which adds an element to the collection, and
5+
* **pop**, which removes the most recently added element that was not yet removed.
6+
The order in which elements come off a stack gives rise to its
7+
alternative name, LIFO (last in, first out). Additionally, a
8+
peek operation may give access to the top without modifying
9+
the stack. The name "stack" for this type of structure comes
10+
from the analogy to a set of physical items stacked on top of
11+
each other, which makes it easy to take an item off the top
12+
of the stack, while getting to an item deeper in the stack
13+
may require taking off multiple other items first
14+
Simple representation of a stack runtime with push and pop operations.
15+
![Stack](https://upload.wikimedia.org/wikipedia/commons/b/b4/Lifo_stack.png)
16+
## References
17+
- [Wikipedia](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))
18+
- [YouTube](https://www.youtube.com/watch?v=wjI1WNcIntg&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8&index=3&)
19+
20+
21+
### ways for adding element in stack:
22+
23+
```push(elem)``` method
24+
25+
### pop()
26+
```pop``` - Takes top element from the stack.
27+
28+
### peek()
29+
```peek``` - Peeks at the top element of the stack.
30+
31+
### size
32+
```size``` - Returns the size of the stack.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* A stack is a data structure that holds a list of elements. A stack works based on the LIFO principle meaning that the most recently added element is the first one to remove.
2+
3+
It has two main operations that occur only at the top of the stack: push and pop. The push operation places an element at the top of stack whereas the pop operation removes an element from the top of the stack. */
4+
5+
function Stack () {
6+
7+
this.count = 0;
8+
this.obj = {};
9+
}
10+
11+
// Adding a value at the top of the stack. And the key of the object will be the current value of count. And the new value that I am pushing will be the value of that key-value pair.
12+
13+
Stack.prototype.push = function(value) {
14+
this.obj[this.count] = value;
15+
this.count++;
16+
}
17+
18+
// remove, or pop out the top-most value from the stack
19+
Stack.prototype.pop = function() {
20+
if (this.count === 0 ) {
21+
return undefined;
22+
}
23+
this.count--;
24+
let result = this.obj[this.count]; // Hook-up to the key of the object that I will remove
25+
delete this.obj[this.count];
26+
return result;
27+
}
28+
29+
// return the length of the stack, which is the size or how many items were inserted
30+
Stack.prototype.size = function () {
31+
return this.count;
32+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Arrow functions cannot be used as methods or constructors - so, I changed my earlier constructor with arrows to regular function in this class
2+
3+
class Stack {
4+
constructor () {
5+
this.data = [];
6+
}
7+
8+
pop()
9+
{
10+
// return top most element in the stack
11+
// and removes it from the stack
12+
// Underflow if stack is empty
13+
if (this.data.length == 0) {
14+
return "Underflow";
15+
} else {
16+
return this.data.pop();
17+
}
18+
}
19+
20+
top () {
21+
return this.data.length;
22+
}
23+
24+
push (...element) {
25+
for (var i of element) {
26+
return this.data.push(i)
27+
}
28+
}
29+
30+
// peek() method looks at the object at the top of this stack without removing it from the stack. The stack is not modified (it does not remove the element; it only returns the element for information purposes).
31+
32+
peek () {
33+
return this.data[this.data.length - 1];
34+
}
35+
36+
clear () {
37+
return this.data = [];
38+
}
39+
40+
length(){
41+
return this.data.length;
42+
}
43+
44+
search (value) {
45+
for (let i = 0; i < this.data.length; i++) {
46+
if (this.data[i] === value) {
47+
return value;
48+
} else {
49+
return false;
50+
}
51+
}
52+
}
53+
}
54+
55+
// Parenthesis matching function to return true or false
56+
57+
function isParenthesisMatched (str) {
58+
59+
let stack = new Stack();
60+
61+
let openingParenthesis = ["[", "(", "{"] ;
62+
let closingParenthesis = ["]", ")", "}"];
63+
64+
/* For each element of the string argument, iterate through each element > check if the current element is any of the opening parenthesis array > If true, push it to stack > IF NOT > there could be 3 cases i.e. ], ), }
65+
> check all the 3 cases switching through them > and comparing this current closing parenthesis with the top element from the stack. Note, that I have only pushed elements from the opening parenthesis to the stack.
66+
> If any match is found from in the closingParenthesis array and the top-most element from stack, then just pop that element from stack. And apply break for this iteration.
67+
> So, for each of the
68+
69+
Explanation that checking only the top-most element of the stack with the closing parenthesis is enough
70+
71+
By the design of this code, I am only making sure that to return true from this function, either (A) all the opening parenthesis will come first ( like in this case - "{[( )]}" ) - or (B) corresponding matching parenthesis will come one after another (side by side) ( like in case "{()}[]" )
72+
73+
In the first case A - The first time I hit a closing parenthesis, the switch function will switch cases, through the 3 of them, and first will pop-out the "(" parenthesis - as the closing ")" will be matched.
74+
Then the next iteration will pop-out the straight bracket "[" - as that will be matched. And lastly the left over curly brace "{"
75+
76+
B> And in the case "{()}[]" - Its eazy to see that the part "{()}" is same as the case-A above, and the part "[ ]" is obvious that the peek element will be the only possible matching element to pop out from the stack.
77+
78+
And with the above code, third case, that this code will return false, is when although there are matched parenthesis
79+
80+
*/
81+
for (let i = 0; i < str.length; i++) {
82+
if (openingParenthesis.includes(str[i])) {
83+
stack.push(str[i]);
84+
} else if (closingParenthesis.includes(str[i])) {
85+
switch (str[i]) {
86+
case "]":
87+
if (stack.peek() === "[") {
88+
stack.pop();
89+
} else {
90+
return false;
91+
}
92+
break;
93+
94+
case "}":
95+
if (stack.peek() === "{") {
96+
stack.pop();
97+
} else {
98+
return false;
99+
}
100+
break;
101+
102+
case ")":
103+
if (stack.peek() === "(") {
104+
stack.pop();
105+
} else {
106+
return false;
107+
}
108+
break;
109+
}
110+
}
111+
}
112+
return stack.length() === 0;
113+
114+
}
115+
116+
console.log(isParenthesisMatched("{[()]}"));
117+
118+
console.log(isParenthesisMatched("{()}[]"));
119+
120+
console.log(isParenthesisMatched("{[)]}"));
121+
122+
console.log(isParenthesisMatched("[)"));

stack-data-structure/stack-postFix.js

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
A postfix expression evaluator works on arithmetic expressions taking the following form:
3+
op1 op2 operator
4+
Using two stacks — one for the operands and one for the operators — design and implement a JavaScript function that converts infix expressions to postfix expressions, and then use the stacks to evaluate the expression.
5+
6+
Infix expression: The expression of the form a op b. When an operator is in-between every pair of operands.
7+
Postfix expression: The expression of the form a b op. When an operator is followed for every pair of operands.
8+
9+
======================
10+
11+
Problem - Statement -
12+
13+
Construct a function named toPostfix that, when given a string containing an expression in infix notation, will return an identical expression in postfix notation.
14+
15+
The operators used will be '+', '-', '*', '/', and '^' with standard precedence rules and left-associativity (meaning the operations are grouped from the left) of all operators but "^".
16+
17+
toPostfix("2+7*5"); // Should return "275*+"
18+
toPostfix("3*3/(7+1)"); // Should return "33*71+/"
19+
toPostfix("5+(6-2)*9+3^(7-1)"); // Should return "562-9*+371-^+"
20+
21+
======================
22+
23+
THe Algo https://www.geeksforgeeks.org/stack-set-2-infix-to-postfix/
24+
25+
1. Scan the infix expression from left to right.
26+
27+
2. If the scanned character is an operand, push it to the result array.
28+
29+
3. Else if the scanned character is a operator
30+
31+
3.1 If the precedence of the scanned operator is greater than the precedence of the top-most operator in the stack(or the stack is empty), push it. NOTE - A OPERATOR WITH HIGHER ORDER IS EXECUTED FIRST PER PEMDAS / BODMAS RULE
32+
33+
3.2 Else, Pop the operator from the stack until the precedence of the scanned operator is less-equal to the precedence of the operator residing on the top of the stack. Push the scanned operator to the stack.
34+
35+
4. If the scanned character is an ‘(‘, push it to the stack.
36+
37+
5. If the scanned character is an ‘)’, pop and output from the stack until an ‘(‘ is encountered.
38+
39+
6. Repeat steps 2-6 until infix expression is scanned.
40+
41+
7. Pop and output from the stack until it is not empty.
42+
*/
43+
44+
function toPostfix (infix) {
45+
46+
let operatorsObj = {
47+
'^': {
48+
precedence: 4,
49+
left: false
50+
},
51+
'*': {
52+
precedence: 3,
53+
left: true
54+
},
55+
'/': {
56+
precedence: 3,
57+
left: true
58+
},
59+
'+': {
60+
precedence: 2,
61+
left: true
62+
},
63+
'-': {
64+
precedence: 2,
65+
left: true
66+
},
67+
};
68+
69+
let postfix = ""; // This is the final string after denoting the expression in postfix format
70+
let operations = [] // This array containing all the 5 individual operations
71+
72+
// start scanning through each of the element of the given expression i.e. the argument 'infix' which in the callback funciton to forEach will be represented by the variable element.
73+
74+
infix.split("").forEach(function(element) {
75+
76+
// first if the current element is a number and not a operator or not a "(" or ")"
77+
if (!isNaN(parseInt(element))) {
78+
postfix += element;
79+
}
80+
// Now if current element is an operator, i.e. one of the 5 properties of operatorsObj is 'true'
81+
else if (operatorsObj[element]) {
82+
83+
let thisOperator = operatorsObj[element];
84+
let topmostOperationStackElement = operations[operations.length - 1];
85+
86+
while (operatorsObj[topmostOperationStackElement] && ((thisOperator.left && thisOperator.precedence <= operatorsObj[topmostOperationStackElement].precedence ))) {
87+
postfix += operations.pop(); // That is, pop this operation and only then push this operation to the final resultant postfix
88+
topmostOperationStackElement = operations[operations.length - 1 ]; // after popping, update the top most operation stack element.
89+
}
90+
operations.push(element);
91+
}
92+
else if (element === "(") {
93+
operations.push(element);
94+
}
95+
else if (element === ")") {
96+
let topmostOperationStackElement = operations[operations.length - 1];
97+
while (topmostOperationStackElement && topmostOperationStackElement !== "(") {
98+
postfix += operations.pop(); // Per the original algo - If the scanned character is an ‘)’, pop and output from the stack until an ‘(‘ is encountered.
99+
topmostOperationStackElement = operations[operations.length - 1];
100+
}
101+
operations.pop();
102+
}
103+
}); // Here ends my forEach operations on the individual elements of the given array
104+
105+
let topmostOperationStackElement = operations[operations.length - 1];
106+
while (topmostOperationStackElement && topmostOperationStackElement !== "(") {
107+
postfix += operations.pop();
108+
topmostOperationStackElement = operations[operations.length - 1];
109+
}
110+
111+
return postfix;
112+
}
113+
114+
console.log(toPostfix("2+7*5"));
115+
console.log(toPostfix("3*3/(7+1)"));
116+
console.log(toPostfix("5+(6-2)*9+3^(7-1)"));

0 commit comments

Comments
 (0)