Skip to content

Commit 04424ce

Browse files
authored
add stack details (#172)
1 parent 7eef611 commit 04424ce

9 files changed

+49
-8
lines changed

array/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func main() {
7676

7777
Accessing an element within an array using an index has O(1) time complexity. This means that regardless of the size of the array, read and write operations for a given element can be performed in constant time.
7878

79-
While arrays are useful for certain tasks, searching an unsorted array can be a time-consuming O(n) operation. Since the target item could be located anywhere in the array, every element must be checked until the item is found. Due to this limitation, alternative data structures such as trees and hash tables are often more suitable for search operations.
79+
While arrays are useful for certain tasks, searching an unsorted array can be a time-consuming O(n) operation. Since the target item could be located anywhere in the array, every element must be checked until the item is found. Due to this limitation, alternative data structures such as [linked-lists](../linkedlist/), [trees](../tree/) and [hash tables](../hashtable/) are often more suitable for search operations.
8080

8181
Addition and deletion operations are O(n) operations in Arrays. Removing an element can create an empty slot that must be eliminated by shifting the remaining items. Similarly, adding items to an array may require shifting existing items to create space for the added item. These inefficiencies can make alternative data structures, such as [trees](../tree) or [hash tables](../hashtable), more suitable for managing operations involving additions and deletions.
8282

linkedlist/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Linked List
22

3-
Linked lists are a collection of nodes, each capable of storing at least one data element and linked to the next node via a reference. One of the key advantages of linked lists over [arrays](../array) is their dynamic size, which allows for items to be added or removed without necessitating the resizing or shifting of other elements.
3+
Linked lists are a collection of nodes, each capable of storing at least one data element and linked to the next node via a reference. One of the key advantages of linked lists over [arrays](../array) has traditionally been seen their dynamic size, which allows for items to be added or removed without necessitating the resizing or shifting of other elements. As shown in [queues](../queue/) with benchmarks this is different in Go due to clever slice sizing techniques used. In practice you can use slices in Go most of the time without a significant performance penalty.
44

55
Two types of linked lists exist: singly linked lists, in which each node is linked only to the next node, and doubly linked lists, in which each node is connected to both the next and previous nodes.
66

stack/README.md

+20-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@ Stacks are data structures that operate on the Last-In-First-Out (LIFO) principl
44

55
One way to visualize stacks is to think of a backpack where items are placed and later removed in reverse order, with the last item added to the bag being the first item removed.
66

7+
The following diagram shows the state of a stack of size 5 when numbers 1 to 4 are pushed to the stack and 4 numbers are popped from the stack. The outcome is reversion of the inserted numbers.
8+
9+
```ASCII
10+
[Figure 1] Push 1,2,3,4 to a stack and then pop 4 times.
11+
12+
┌───┐┌───┐┌───┐┌───┐┌───┐ ┌───┐┌───┐┌───┐┌───┐
13+
│ ││ ││ ││ ││ │ │ ││ ││ ││ │
14+
├───┤├───┤├───┤├───┤├───┤ ├───┤├───┤├───┤├───┤
15+
│ ││ ││ ││ ││ 4 │ │ ││ ││ ││ │
16+
├───┤├───┤├───┤├───┤├───┤ ├───┤├───┤├───┤├───┤
17+
│ ││ ││ ││ 3 ││ 3 │ │ 3 ││ ││ ││ │
18+
├───┤├───┤├───┤├───┤├───┤ ├───┤├───┤├───┤├───┤
19+
│ ││ ││ 2 ││ 2 ││ 2 │ │ 2 ││ 2 ││ ││ │
20+
├───┤├───┤├───┤├───┤├───┤ ├───┤├───┤├───┤├───┤
21+
│ ││ 1 ││ 1 ││ 1 ││ 1 │ │ 1 ││ 1 ││ 1 ││ │
22+
└───┘└───┘└───┘└───┘└───┘ └───┘└───┘└───┘└───┘
23+
```
24+
725
## Implementation
826

927
In Go, stacks can be implemented using doubly [linked lists](../linkedlist/) or [arrays and slices](../array/). Here is a linked list implementation:
@@ -75,13 +93,13 @@ func pop() (int, error) {
7593

7694
Push and pop operations in stacks are considered O(1) operations, making them highly efficient. Additionally, many machines have built-in stack instruction sets, further increasing their performance. Stacks' unique efficiency and usefulness have solidified their place as one of the most fundamental data structures, second only to [arrays](../array).
7795

78-
Resizing the slice and item shifting maybe necessary in the slice implementation, hence traditionally this implementation is seen as O(n). As shown in the complexity of [queue](../queue/README.md) because of the intelligent ways Go resizes the slices this is not a problem and the slice implementation of both stack and queue will perform better than the linked list implementation.
96+
Resizing the slice and item shifting maybe necessary in the slice implementation, hence traditionally this implementation is seen as O(n). As shown in the complexity of [queue](../queue/README.md) because of the intelligent ways Go resizes the slices this is not a problem and the slice implementation of both stack and queue in Go will perform better than the linked list implementation.
7997

8098
## Application
8199

82100
Stacks are helpful when LIFO operations are desired. Many [graph](../graph) problems are solved with stacks.
83101

84-
During process execution, a portion of memory known as the "stack" is reserved to hold stack frames. Whenever a function is called, relevant data such as parameters, local variables, and return values are stored within a frame to be accessed after the function has been completed. When an excessive number of function calls or an infinite recursive function are made, the computer's ability to store all of this information is exceeded. This results in the well-known stack overflow error.
102+
During process execution in operating systems, memory is divided into "stack" and "heap". The stack portion of the memory is used whenever a function is called. Relevant data such as parameters, local variables, and return values are stored within a frame in a stack to be popped after the function has been completed. When an excessive number of function calls or an infinite recursive function are made, the computer's ability to store all of this information is exceeded. This results in the well-known stack overflow error.
85103

86104
## Rehearsal
87105

stack/balancing_symbols_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ TestIsExpressionBalanced tests solution(s) with the following signature and prob
88
func IsExpressionBalanced(s string) bool
99
1010
Given a set of symbols including []{}(), determine if the input is is balanced or not.
11+
12+
For example {{(}} is not balanced because there is no closing `)` while {{()}} is balanced.
1113
*/
1214
func TestIsExpressionBalanced(t *testing.T) {
1315
tests := []struct {

stack/basic_calculator_test.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ import "testing"
44

55
/*
66
TestBasicCalculator tests solution(s) with the following signature and problem description:
7+
78
func BasicCalculator(input string) (float64, error)
89
910
Given an expression containing integers, parentheses and the four basic arithmetic operations
10-
like 1*2+3+4*5 calculate the expression into a numerical value like 25.
11+
{*,/,+,-} starting from the highest priority to lowest.
12+
13+
For example given 1*2+3+4*5 return 25 because (4*5) + (1*2) + 3 = 25.
1114
*/
1215
func TestBasicCalculator(t *testing.T) {
1316
tests := []struct {

stack/evaluate_postfix_test.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,16 @@ TestEvaluatePostfix tests solution(s) with the following signature and problem d
77
88
func EvaluatePostfixExpression(expression []string) (float64, error)
99
10-
Given a postfix expression like 1 2 3 + *, calculate the expression e.g. 5.
10+
Given a postfix expression calculate its the value.
11+
12+
The postfix expression is a list of strings where each string is either an operator like
13+
arithmetic symbols or an operand that are numbers.
14+
15+
To evaluate the postfix expression, we start scanning the expression from left to right.
16+
If the current element is an operator we apply the operand to the last two operands we read
17+
we then remove the operator and replace the two operands with the results of the operation.
18+
19+
For example given 1 2 3 + *, return 5 because 1 * (2 + 3) = 5.
1120
*/
1221
func TestEvaluatePostfix(t *testing.T) {
1322
tests := []struct {

stack/infix_to_postfix_test.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,13 @@ TestInfixToPostfix tests solution(s) with the following signature and problem de
1010
1111
func InfixToPostfix(infix []string) []string
1212
13-
Given an infix expression e.g. 1*2+3+4*5, convert it to a postfix expression
14-
like 1 2 * 3 + 4 5 * supporting the four basic arithmetic operations and parentheses.
13+
Given an infix expression convert it to a postfix expression supporting the four basic arithmetic
14+
operations and parentheses.
15+
16+
Infix expression is how humans typically write arithmetic expressions like 1*2+3+4*5 which
17+
is equivalent of (1*2) + 3 + (4*5).
18+
19+
For example given 1*2+3+4*5, return 1 2 * 3 + 4 5 * which both evaluate to 25.
1520
*/
1621
func TestInfixToPostfix(t *testing.T) {
1722
tests := []struct {

stack/longest_valid_parentheses_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ TestLongestValidParentheses tests solution(s) with the following signature and p
99
1010
Given a string containing parentheses, find the length of the longest valid (well-formed)
1111
parentheses substring.
12+
13+
For example given "(()", return 2 because the longest valid parentheses substring is "()".
1214
*/
1315
func TestLongestValidParentheses(t *testing.T) {
1416
tests := []struct {

stack/max_stack_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ TestMaxStack tests solution(s) with the following signature and problem descript
1212
func (maxStack *MaxStack) Max() int
1313
1414
Implement a stack that can return the max of element it contains.
15+
16+
For example if we push {2,4,5} to the stack, max should return 5.
1517
*/
1618
func TestMaxStack(t *testing.T) {
1719
tests := []struct {

0 commit comments

Comments
 (0)