catalogue
1, Definition and characteristics of 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.6 preview stack top elements
2.2.1 structure definition of chain stack
2.2.2 initialization of chain stack
2.2.4 stack (the header insertion method of linked list is used here)
3.3 inverse Polish expression: it is required to input infix expression and output suffix expression
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 [0255], 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!