# Data structure and algorithm foundation - Go language version - 2. Stack

Keywords: Go Back-end

catalogue

preface

1, Definition and characteristics of stack?

2, Implementation of stack

2.1 sequence stack

2.1.1 structure definition of sequence stack

2.1.2 initialization of sequence stack

2.1.3 judge whether the stack is empty or full

2.1.4 stacking

2.1.5 out of stack

2.1.6 preview stack top elements

2.2 chain stack

2.2.1 structure definition of chain stack

2.2.2 initialization of chain stack

2.1.3 stack empty judgment

2.2.4 stack (the header insertion method of linked list is used here)

2.2.5   Out of stack

3, Practice

3.1 hexadecimal conversion, design a function. It is required to input a hexadecimal number, which can be output and converted into the corresponding hexadecimal number.

3.2 bracket matching: enter any number of strings containing only brackets, and the function can judge whether the number and type of brackets in the string match

3.3 inverse Polish expression: it is required to input infix expression and output suffix expression

summary

# preface

This paper will systematically introduce the structure and characteristics of stack, and give how to realize the stack of sequential structure and chain structure in go language. Finally, the sequential stack is used to complete several exercises.

# 1, Definition and characteristics of stack?

• Definition of stack: stack is a linear table that is restricted to insert and delete operations only at the end of the table
• Stack features: first in first out, last in first out

# 2, Implementation of stack

## 2.1 sequence stack

### 2.1.1 structure definition of sequence stack

• The container structure of the stack is designed as follows • code implementation
```type stack struct{
top int  // Points to the next position of the top element of the stack
base int // Always point to the bottom of the stack
container []int //Dynamic capacity expansion can be achieved by using slices
length int // Record the number of elements in the current stack
size int // Record the maximum capacity of the current stack
}
```

### 2.1.2 initialization of sequence stack

```func initStack(size int)*stack{
return &stack{
top:0,
base:0,
container:make([]int,size,size), //There are two methods: one is to define the length as 0 and append it with the append() function when entering the stack, but it is troublesome to erase the value of the underlying array when bouncing the stack. The other is to define the length as size and directly assign the index value when entering the stack
length:0,
size:size,
}
}```

### 2.1.3 judge whether the stack is empty or full

```func (s *stack)isValid()bool{
return s.length==0
}

func (s *stack)isFull()bool{
return s.length==s.size
}```

### 2.1.4 stacking

```func (s *stack)push(data int)error{
if s.isFull(){
return errors.New("the stack is full,can not push any value\n")
}
s.container[s.top]=data //Append elements to the end of the table (i.e. the top of the stack)
s.top++ // Keep top pointing to the next position of the top element of the stack
s.length++
return nil
}```

### 2.1.5 out of stack

```func (s *stack)pop()(int,error){
if s.isValid(){
return -1,errors.New("the stack is valid,can not pop any value\n")
}
s.top--  // First point top to the current stack top element
s.length--
return s.container[s.top],nil
}```

### 2.1.6 preview stack top elements

```func (s *stack)peek()string{
return s.container[top-1]
}```

## 2.2 chain stack

### 2.2.1 structure definition of chain stack

```type sNode struct{
data int
next *sNode
}

func newSNode(data int)*sNode{
return &sNode{
data:data,
next:nil,
}
}

type lStack struct{
top *sNode //The top pointer points to the chain header node and does not store data. The header node always points to the top element of the stack
length int
}

```

### 2.2.2 initialization of chain stack

```// Initialization of chain stack
func initLStack()*lStack{
return &lStack{
top:newSNode(-1),
length:0,
}
}```

### 2.1.3 stack empty judgment

```// Judge whether the chain stack is empty
func (ls *lStack)isValid()bool{
return ls.length==0
}```

### 2.2.4 stack (the header insertion method of linked list is used here)

• thinking • The code is implemented as follows
```// Chain stack
func (ls *lStack)push(data int){
temp := newSNode(data)
temp.next =ls.top.next
ls.top.next=temp
ls.length++
}```

### 2.2.5   Out of stack

• thinking •   The code is implemented as follows
```// Chain stack out of stack
func (ls *lStack)pop()(int,error){
if ls.isValid(){
return -1,errors.New("the stack is valid,can not pop any value\n")
}
result := ls.top.next
ls.top.next = result.next
result.next = nil
ls.length--
return result.data,nil

}```

# 3, Practice

## 3.1 hexadecimal conversion, design a function. It is required to input a hexadecimal number, which can be output and converted into the corresponding hexadecimal number.

• thinking •   The code is implemented as follows
```const(
Binary = 2
Octcal = 8
Hex = 16
)

// The default input data range of this function is , and the conversion to A.B, C, D and e when hexadecimal is greater than 9 is not considered
func trans(data int,convert int)[]int{
s := initStack(8)
result := make([]int,0,8)
remainder := data % convert // Mod
for data != 0{ // Finally, the data will be divided to 0
s.push(remainder) // Stack remainder
data = data /  convert // Update data
remainder = data % convert
}

length := s.length
for i:=0 ; i < length ; i++{
result = append(result,s.pop())
}
return result
}```

## 3.2 bracket matching: enter any number of strings containing only brackets, and the function can judge whether the number and type of brackets in the string match

• thinking
• Encountered left parenthesis' (',' [',' {'on the stack
• If the right bracket is encountered, pop the stack and perform symbol matching at the same time. If it does not match, false is returned. If the stack is empty, there are too many right brackets
• After scanning the string, judge whether the stack is not empty. If it is not empty, it indicates that there are more left parentheses in the stack
• The code is implemented as follows
```func match(str string)bool{
s := initStack(len(str)) // Initialize a stack
for _,v := range str{
switch string(v){ // Each v of for range is a run type, which can only be compared after being converted into a string
case "(","[","{":
s.push(string(v))    // If the left bracket is encountered, it will be put on the stack
case ")":
temp,err := s.pop()  // If the right parenthesis is encountered, the matching starts. If it does not match or the stack is empty (pop() will return an error), fasle is returned
if err != nil || temp != "("{
return false
}
case "]":
temp,err := s.pop()
if err != nil || temp != "["{
return false
}
case "}":
temp,err := s.pop()
if err != nil || temp != "{"{
return false
}
default:
return false

}
}

if !s.isValid(){  //If the stack is not empty after the string is scanned, the left bracket is redundant
return false
}

return true

}

func main(){
str1 := "(()"
str2 := "())"
str3 := "{[()]}"

fmt.Println(match(str1))  //Output false
fmt.Println(match(str2))  //Output false
fmt.Println(match(str3))  //Output true
}```

## 3.3 inverse Polish expression: it is required to input infix expression and output suffix expression

• Idea: scan to digital direct output, scan to operator:
• The priority is higher than the stack top operator and is directly put on the stack
• The priority is lower than the stack top operator. Pop up the stack top operator and output it until the stack top operator has a lower priority than the currently scanned operator, and then input the currently scanned operator into the stack
• When "(" is encountered, it will be put on the stack unconditionally until ")" is encountered. All operators between two parentheses will be popped and output
• After scanning the string, pop up the remaining elements in the stack
• The code is implemented as follows
• ```func postFix(str string)[]string{
s := initStack(len(str)) // Initialize a stack
result := make([]string,0,len(str)) // Initialize a slice to load the results

for _,v := range str{
switch string(v){
case "1","2","3","4","5","6","7","8","9":
result = append(result,string(v)) // Numbers encountered are appended directly to the result
case "*","/": // Encountered "*", "/", pop up "*", "/" at the top of the stack
temp := s.peek()
for temp=="*"||temp=="/"{
result = append(result,string(temp))
s.pop()
temp = s.peek()
}
s.push(string(v))
case "+","-": //When "+", "-", the priority is the lowest, pop up all symbols in the stack
temp := s.peek()
for temp=="*"||temp=="/"||temp=="+"||temp=="-"{
result = append(result,string(temp))
s.pop()
temp = s.peek()
}
case "(":
s.push(string(v))
case ")": //If the right parenthesis is encountered, all parentheses contained between the left and right parentheses will pop up
temp := s.peek()
for temp != "("{
result = append(result,string(temp))
s.pop()
temp = s.peek()

}
s.pop() //Pop up left parenthesis
default:
break
}

}

// Pop up the remaining symbols in the stack
length := s.length
for i:=0;i<length;i++{
v ,_:= s.pop()
result = append(result,v)
}

return result
}

func main() {
str := "1+2*(4-3*7/2)-5/6"
result := postFix(str)
fmt.Println(result) // Output: [1 2 4 3 7 * 2 / - * + 5 6 / -]
}```

# summary

The above is the use of go language to build the stack and introduce some related applications. If there are mistakes, I hope you can correct them.

Endless life, coding more than!

Posted by allanric on Thu, 18 Nov 2021 08:10:35 -0800