数据结构之Go实现栈


栈的基础知识


栈的基本概念

(1)栈的定义

栈是一种只能在一端进行插入或删除操作的线性表,其中允许进行插入或删除操作的一端称为栈顶(Top),栈的插入和删除操作一般称为入栈和出栈。

栈的底端称为栈底,栈底是固定不变的,栈顶由一个称为栈顶指针的位置指示器(一个变量)来指示,对于顺序栈,是记录栈顶元素所在数组位置标号的一个整型变量;对于链式栈,是记录栈顶元素所在结点地址的指针,它是动态变化的。

(2)栈的特征

栈的主要特点是先进后出( FILO )。

(3)栈的存储结构

栈按照存储结构分为两种:顺序栈和链式栈。栈本质上是线性表,而线性表有两种主要的存储结构——顺序表和链表,因此栈也同样有对应的两种存储结构。

(4)栈的数学性质

当 n 个元素以某种顺序进栈,并且可在任意时刻出栈(在满足先进后出的前提下)时,所获得的元素排列的数目 N 恰好满足 Catalan 函数的计算。


栈的结构体定义


(1)顺序栈的结构体定义如下:

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

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

(2) 链栈的结构体定义如下:

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

type LinkStack struct {
    
    
        Top    *StackNode
        Length 	int
}

栈的实现


数组栈

(1)数组栈的基本操作如下代码所示。

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

(2)在任意目录下创建项目,编写一个名为 seqstack.go 的程序实现以上的操作,该程序的代码如下所示。

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)在该项目的目录下编写一个名为 seqstack_test.go 程序测试以上的功能逻辑是否正确,该程序的具体代码如下所示。

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)在该项目的目录下执行 go test 命令进行验证测试,程序运行的结果如下所示。

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

切片栈

(1)切片栈的基本操作如下代码所示。

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

(2)在任意目录下创建项目,编写一个名为 slicestack.go 的程序实现以上的功能,该程序的代码如下所示。

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)在该项目的目录下编写一个名为 slicestack_test.go 程序测试以上的的功能逻辑是否正确,该程序的具体代码如下所示。

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)在该项目的目录下执行 go test 命令进行测试验证,程序运行的结果如下所示。

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

链表栈

(1)链表栈的基本操作如下代码所示。

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

(2)在任意目录下创建项目,编写一个名为 linkedstack.go 的程序实现以上的操作,该程序的代码如下所示。

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)在该项目的目录下编写一个名为 linkedstack_test.go 程序测试以上的的功能逻辑是否正确,该程序的具体代码如下所示。

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)在该项目的目录下执行 go test 命令进行测试验证,程序运行的结果如下所示。

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 

  • 参考书籍:《数据结构教程 第6版》(李春葆 主编)

  • 参考书籍:《数据结构 C语言版》(严蔚敏、李冬梅、吴伟民著)

猜你喜欢

转载自blog.csdn.net/qq_46457076/article/details/129819972