Go implementation stack of data structure


Basic knowledge of the stack


The basic concept of the stack

(1) Definition of stack

A stack is a linear table that can only be inserted or deleted at one end. The end that allows insertion or deletion is called the top of the stack (Top), and the insertion and deletion operations of the stack are generally called stacking and popping.

The bottom of the stack is called the bottom of the stack, and the bottom of the stack is fixed. The top of the stack is indicated by a position indicator (a variable) called the top pointer of the stack. For a sequential stack, it is the position label of the array that records the top element of the stack An integer variable; for a linked stack, it is a pointer that records the address of the node where the top element of the stack is located, and it changes dynamically.

(2) Characteristics of the stack

The main feature of the stack is first in last out ( FILO ).

(3) The storage structure of the stack

The stack is divided into two types according to the storage structure: sequential stack and chain stack. The stack is essentially a linear list, and the linear list has two main storage structures - sequential list and linked list, so the stack also has two corresponding storage structures.

(4) Mathematical properties of the stack

When n elements are pushed into the stack in a certain order and can be popped out of the stack at any time (under the premise of satisfying first-in-last-out), the number N of obtained element arrangements just satisfies the calculation of the Catalan function.


The structure definition of the stack


(1) The structure of the sequential stack is defined as follows:

// Arrary
type ArrayStack struct {
    
    
        Data [MaxSize]interface{
    
    }
        Top  int
}

// Slice
type SliceStack struct {
    
    
        Data []interface{
    
    }
        Top  int
}

(2) The structure of the chain stack is defined as follows:

type StackNode struct {
    
    
        Value interface{
    
    }
        Next  *StackNode
}

type LinkStack struct {
    
    
        Top    *StackNode
        Length 	int
}

Implementation of the stack


array stack

(1) The basic operation of the array stack is shown in the following code.

type Operate interface {
    
    
		// 初始化栈 
        InitSeqStack()
        // 判断栈是否为空
        IsEmpty() bool
        // 获取栈的长度
        Len() int
        // 输出栈
        DisplayStack()
        // 获取栈顶元素
        Peek() interface{
    
    }
        // 元素进栈
        Push(v interface{
    
    }) error
        // 元素出栈
        Pop() (v interface{
    
    }, err error)
}

(2) Create a project in any directory, and write a seqstack.goprogram named to realize the above operations. The code of the program is as follows.

package SeqStack

import (
        "errors"
        "fmt"
)

const MaxSize = 20

type SeqStack struct {
    
    
        Data [MaxSize]interface{
    
    }
        Top  int
}

func NewSeqStack() *SeqStack {
    
    
        return new(SeqStack)
}

// 相关操作的接口定义
type Operate interface {
    
    
        InitSeqStack()
        IsEmpty() bool
        Len() int
        DisplayStack()
        Peek() interface{
    
    }
        Push(v interface{
    
    }) 
        Pop() (v interface{
    
    })
}


// 初始化顺序栈
func (s *SeqStack) InitSeqStack() {
    
    
        s.Top = -1
}

// 获取栈的长度
func (s *SeqStack) Len() int {
    
    
        return s.Top + 1
}

// 判断栈是否为空
func (s *SeqStack) IsEmpty() bool {
    
    
        return s.Top == -1
}

// 获取栈顶元素
func (s *SeqStack) Peek() interface{
    
    } {
    
    
        if s.IsEmpty() {
    
    
                panic(errors.New(("The SeqStack is empty!"))
        } else {
    
    
                return s.Data[s.Top]
        }
}

// 输出栈中的元素
func (s *SeqStack) DisplayStack() {
    
    
        if s.IsEmpty() {
    
    
        		fmt.Printf("The SeqStack is empty!\n")
        } else {
    
    
        		i := 0
        		fmt.Printf("栈中的元素为: ")
        		for i < s.Len() {
    
    
                		fmt.Printf("%d ", s.Data[i])
                		i++
        		}
        		fmt.Println()
		}
}

// 进栈操作
func (s *SeqStack) Push(v interface{
    
    }) {
    
    
        if s.Top == MaxSize-1 {
    
    
                panic(errors.New("The SeqStack is full!\n"))
        } else {
    
    
                s.Top++
                s.Data[s.Top] = v
                fmt.Printf("Elem %d is pushed into the SeqStack!\n", v)
        }
}

// 出栈操作
func (s *SeqStack) Pop() (v interface{
    
    }) {
    
    
        if s.IsEmpty() {
    
    
                panic(errors.New("The SeqStack is full!\n"))
        } else {
    
    
                v = s.Data[s.Top]
                s.Top--
                fmt.Printf("Elem %d is poped from the SeqSatck!\n", v)
                return v
        }
}

(3) Write a program named in the directory of the project seqstack_test.goto test whether the above functional logic is correct. The specific code of the program is as follows.

package SeqStack

import (
        "fmt"
        "testing"
)

func TestSeqStack(t *testing.T) {
    
    
        var s Operate
        s = NewSeqStack()
        s.InitSeqStack()
        s.Push(3)
        s.Push(2)
        s.Push(1)
        s.DisplayStack()
        fmt.Printf("The SeqStack's top elem is %d\n", s.Peek())
        s.Pop()
        s.DisplayStack()
        fmt.Printf("The SeqStack's length is %d\n", s.Len())
}

(4) Execute the command in the directory of the project go testto perform the verification test, and the results of the program operation are as follows.

Elem 3 is pushed into the SeqStack!
Elem 2 is pushed into the SeqStack!
Elem 1 is pushed into the SeqStack!
栈中的元素为: 3 2 1 
The SeqStack's top elem is 1
Elem 1 is poped from the SeqSatck!
3 2 
The SeqStack's length is 2

slice stack

(1) The basic operation of the slice stack is shown in the following code.

type Operate interface {
    
    
		// 初始化栈 
        InitSliceStack()
        // 判断栈是否为空
        IsEmpty() bool
        // 获取栈的长度
        Len() int
        // 输出栈
        DisplayStack()
        // 获取栈顶元素
        Peek() interface{
    
    }
        // 元素进栈
        Push(v interface{
    
    })
        // 元素出栈
        Pop() (v interface{
    
    })
}

(2) Create a project in any directory, and write a slicestack.goprogram named to realize the above functions. The code of the program is as follows.

package SliceStack

import (
        "errors"
        "fmt"
)

type SliceStack struct {
    
    
        Data []interface{
    
    }
        Top  int
}

// 相应操作的接口
type Operate interface {
    
    
        InitSliceStack()
        IsEmpty() bool
        Len() int
        DisplayStack()
        Peek() interface{
    
    }
        Push(v interface{
    
    })
        Pop() interface{
    
    }
}

func NewSliceStack() *SliceStack {
    
    
        return new(SliceStack)
}

// 初始化栈
func (s *SliceStack) InitSliceStack() {
    
    
        s.Top = -1
}

// 判断栈是否为空
func (s *SliceStack) IsEmpty() bool {
    
    
        return s.Top == -1
}

// 获取栈的长度
func (s *SliceStack) Len() int {
    
    
        return s.Top + 1
}

// 输出栈中的元素
func (s *SliceStack) DisplayStack() {
    
    
		if s.IsEmpty() {
    
    
				fmt.Printf("The SliceStack is empty!\n")
		} else {
    
    
				fmt.Printf("栈中的元素为: ")
        		for _, value := range s.Data {
    
    
                		fmt.Printf("%d ", value)
        		}
        		fmt.Println()
        }
}

// 获取栈顶的元素
func (s *SliceStack) Peek() interface{
    
    } {
    
    
        if s.IsEmpty() {
    
    
                panic(errors.New("The SliceStack is empty!\n"))
        }
        return s.Data[s.Top-1]
}

// 进栈操作
func (s *SliceStack) Push(v interface{
    
    }) {
    
    
        s.Data = append(s.Data, v)
        s.Top++
        fmt.Printf("Elem %d is pushed into the SliceSatck!\n", v)
}

// 出栈操作
func (s *SliceStack) Pop() interface{
    
    } {
    
    
        if s.IsEmpty() {
    
    
                panic(errors.New("The SliceStack is Empty!\n"))
        }
        v := s.Data[s.Top]
        s.Top--
        s.Data = append(s.Data[:s.Top+1])
        fmt.Printf("Elem %d is poped from the SliceStack!\n", v)
        return v
}

(3) Write a program named in the directory of the project slicestack_test.goto test whether the above function logic is correct. The specific code of the program is as follows.

package SliceStack

import (
        "fmt"
        "testing"
)

func TestSliceStack(t *testing.T) {
    
    
        var s Operate
        s = NewSliceStack()
        s.InitSliceStack()
        s.Push(2)
        s.Push(5)
        s.Push(7)
        s.Push(0)
        s.Push(3)
        s.DisplayStack()
        fmt.Printf("The SliceStack's length is %d\n", s.Len())
        s.Pop()
        fmt.Printf("The SliceStack top elem is %d\n", s.Peek())
        s.DisplayStack()
}

(4) Execute the command in the directory of the project go testfor test verification, and the result of the program operation is as follows.

The SliceStack is empty!
Elem 2 is pushed into the SliceSatck!
Elem 5 is pushed into the SliceSatck!
Elem 7 is pushed into the SliceSatck!
Elem 0 is pushed into the SliceSatck!
Elem 3 is pushed into the SliceSatck!
栈中的元素为: 2 5 7 0 3 
The SliceStack's length is 5
Elem 3 is poped from the SliceStack!
The SliceStack top elem is 7
栈中的元素为: 2 5 7 0

linked list stack

(1) The basic operation of the linked list stack is shown in the following code.

type Operate interface {
    
    
		// 初始化链表栈
        InitStack()
        // 判断链表栈是否为空
        IsEmpty() bool
        // 获取链表栈的长度
        Len() int
        // 输出栈中元素
        DisplayStack()
        // 获取链表栈栈顶元素
        Peek() interface{
    
    }
        // 元素进栈
        Push(v interface{
    
    })
        // 元素出栈
        Pop() interface{
    
    }
}

(2) Create a project in any directory, and write a linkedstack.goprogram named to realize the above operations. The code of the program is as follows.

package LinkedStack

import (
        "errors"
        "fmt"
)

type LinkedStackNode struct {
    
    
        Value interface{
    
    }
        Next  *LinkedStackNode
}

type LinkedStack struct {
    
    
        Top    *LinkedStackNode
        Length int
}

func NewLinkedStackNode() *LinkedStackNode {
    
    
        return new(LinkedStackNode)
}

func NewLinkedStack() *LinkedStack {
    
    
        return &LinkedStack{
    
    NewLinkedStackNode(), 0}
}

// 相应的操作接口
type Operate interface {
    
    
        InitStack()
        IsEmpty() bool
        Len() int
        DisplayStack()
        Peek() interface{
    
    }
        Push(v interface{
    
    })
        Pop() interface{
    
    }
}

// 初始化链表栈
func (s *LinkedStack) InitStack() {
    
    
		// 带头结点
        s.Top.Next = nil
}

// 判断栈是否为空
func (s *LinkedStack) IsEmpty() bool {
    
    
        return s.Top.Next == nil
}

// 获取栈的长度
func (s *LinkedStack) Len() int {
    
    
        return s.Length
}

// 输出栈中元素(从栈顶到栈底)
func (s *LinkedStack) DisplayStack() {
    
    
        if s.IsEmpty() {
    
    
                fmt.Printf("The LinkedStack is empty!\n")
        } else {
    
    
                tail := s.Top
                fmt.Printf("栈中元素(从栈顶到栈底)为: ")
                for i := 0; i < s.Len(); i++ {
    
    
                        fmt.Printf("%d ", tail.Value)
                        tail = tail.Next
                }
                fmt.Println()
        }
}

// 获取栈顶元素
func (s *LinkedStack) Peek() interface{
    
    } {
    
    
        if s.IsEmpty() {
    
    
                panic(errors.New("The LinkedStack is empty!"))
        } else {
    
    
                return s.Top.Value
        }
}

// 进栈操作
func (s *LinkedStack) Push(v interface{
    
    }) {
    
    
        tmp := &LinkedStackNode{
    
    0, s.Top}
        tmp.Value = v
        s.Top = tmp
        fmt.Printf("Elem %d is pushed into the LinkedStack!\n", v)
        s.Length++
}

// 出栈操作
func (s *LinkedStack) Pop() interface{
    
    } {
    
    
        if s.IsEmpty() {
    
    
                panic(errors.New("The LinkedStack is empty!\n"))
        } else {
    
    
                v := s.Top.Value
                s.Top = s.Top.Next
                s.Length--
                fmt.Printf("Elem %d is poped from the LinkedStack!\n", v)
                return v
        }
}

(3) Write a program named in the directory of the project linkedstack_test.goto test whether the above function logic is correct. The specific code of the program is as follows.

package LinkedStack

import (
        "fmt"
        "testing"
)

func TestLinkedStack(t *testing.T) {
    
    
        var s Operate
        s = NewLinkedStack()
        s.InitStack()
        s.DisplayStack()
        s.Push(3)
        s.Push(2)
        s.Push(1)
        s.DisplayStack()
        s.Pop()
        s.Pop()
        s.Push(6)
        s.Pop()
        fmt.Printf("The LinkedStack's length is %d\n", s.Len())
        fmt.Printf("The LinkedStack top elem is %d\n", s.Peek())
        s.Push(9)
		s.DisplayStack()
}

(4) Execute the command in the directory of the project go testfor test verification, and the result of the program operation is as follows.

The LinkedStack is empty!
Elem 3 is pushed into the LinkedStack!
Elem 2 is pushed into the LinkedStack!
Elem 1 is pushed into the LinkedStack!
栈中元素为: 1 2 3 
Elem 1 is poped from the LinkedStack!
Elem 2 is poped from the LinkedStack!
Elem 6 is pushed into the LinkedStack!
Elem 6 is poped from the LinkedStack!
The LinkedStack's length is 1
The LinkedStack top elem is 3
Elem 9 is pushed into the LinkedStack!
栈中元素为: 9 3 

  • Reference book: "Data Structure Course 6th Edition" (Edited by Li Chunbao)

  • Reference book: "Data Structure C Language Edition" (by Yan Weimin, Li Dongmei, Wu Weimin)

Guess you like

Origin blog.csdn.net/qq_46457076/article/details/129819972