From 27e4402ecaf452904a0525ad253def305852e364 Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Tue, 29 Nov 2022 01:09:12 +0800 Subject: [PATCH] feat(stack): implement stack in golang code --- .../go/chapter_stack_and_queue/array_stack.go | 73 +++++++++++++++ .../linkedlist_stack.go | 79 ++++++++++++++++ codes/go/chapter_stack_and_queue/stack.go | 18 ++++ .../go/chapter_stack_and_queue/stack_test.go | 93 +++++++++++++++++++ 4 files changed, 263 insertions(+) create mode 100644 codes/go/chapter_stack_and_queue/array_stack.go create mode 100644 codes/go/chapter_stack_and_queue/linkedlist_stack.go create mode 100644 codes/go/chapter_stack_and_queue/stack.go create mode 100644 codes/go/chapter_stack_and_queue/stack_test.go diff --git a/codes/go/chapter_stack_and_queue/array_stack.go b/codes/go/chapter_stack_and_queue/array_stack.go new file mode 100644 index 0000000..f3a8a28 --- /dev/null +++ b/codes/go/chapter_stack_and_queue/array_stack.go @@ -0,0 +1,73 @@ +// File: array_stack.go +// Created Time: 2022-11-26 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +import ( + "fmt" + "strconv" + "strings" +) + +// ArrayStack 基于数组实现的栈 +type ArrayStack struct { + data []int // 数据 +} + +func NewArrayStack() *ArrayStack { + return &ArrayStack{ + // 设置栈的长度为 0,容量为 16 + data: make([]int, 0, 16), + } +} + +// Size 栈的长度 +func (s *ArrayStack) Size() int { + return len(s.data) +} + +// IsEmpty 栈是否为空 +func (s *ArrayStack) IsEmpty() bool { + return s.Size() == 0 +} + +// Push 入栈 +func (s *ArrayStack) Push(v int) { + // 切片会自动扩容 + s.data = append(s.data, v) +} + +func (s *ArrayStack) Pop() any { + // 弹出栈前,先判断是否为空 + if s.IsEmpty() { + return nil + } + val := s.Peek() + s.data = s.data[:len(s.data)-1] + return val +} + +func (s *ArrayStack) Peek() any { + if s.IsEmpty() { + return nil + } + val := s.data[len(s.data)-1] + return val +} + +func (s *ArrayStack) Print() { + fmt.Println(s.toString()) +} + +func (s *ArrayStack) toString() string { + var builder strings.Builder + if s.IsEmpty() { + return "empty stack" + } + for i := len(s.data) - 1; i > 0; i-- { + builder.WriteString(strconv.Itoa(s.data[i]) + " -> ") + } + builder.WriteString(strconv.Itoa(s.data[0])) + return builder.String() +} diff --git a/codes/go/chapter_stack_and_queue/linkedlist_stack.go b/codes/go/chapter_stack_and_queue/linkedlist_stack.go new file mode 100644 index 0000000..88fe4dc --- /dev/null +++ b/codes/go/chapter_stack_and_queue/linkedlist_stack.go @@ -0,0 +1,79 @@ +// File: linkedlist_stack.go +// Created Time: 2022-11-28 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +import ( + "container/list" + "fmt" + "strings" +) + +// LinkedListStack 基于链表实现的栈, 使用内置包 list 来实现栈 +type LinkedListStack struct { + list *list.List +} + +// NewLinkedListStack 初始化链表 +func NewLinkedListStack() *LinkedListStack { + return &LinkedListStack{ + list: list.New(), + } +} + +// Push 入栈 +func (s *LinkedListStack) Push(value any) { + s.list.PushBack(value) +} + +// Pop 出栈 +func (s *LinkedListStack) Pop() any { + if s.IsEmpty() { + return nil + } + e := s.list.Back() + s.list.Remove(e) + return e.Value +} + +// Peek 访问栈顶元素 +func (s *LinkedListStack) Peek() any { + if s.IsEmpty() { + return nil + } + e := s.list.Back() + return e.Value +} + +// Size 获取栈的长度 +func (s *LinkedListStack) Size() int { + return s.list.Len() +} + +// IsEmpty 判断栈是否为空 +func (s *LinkedListStack) IsEmpty() bool { + return s.list.Len() == 0 +} + +func (s *LinkedListStack) Print() { + fmt.Println(s.toString()) +} + +func (s *LinkedListStack) toString() any { + var builder strings.Builder + if s.IsEmpty() { + fmt.Println("empty stack") + return nil + } + e := s.list.Back() + // 强转为 string, 会影响效率 + str := fmt.Sprintf("%v", e.Value) + for e.Prev() != nil { + builder.WriteString(str + " -> ") + e = e.Prev() + str = fmt.Sprintf("%v", e.Value) + } + builder.WriteString(str) + return builder.String() +} diff --git a/codes/go/chapter_stack_and_queue/stack.go b/codes/go/chapter_stack_and_queue/stack.go new file mode 100644 index 0000000..7215224 --- /dev/null +++ b/codes/go/chapter_stack_and_queue/stack.go @@ -0,0 +1,18 @@ +// File: stack.go +// Created Time: 2022-11-26 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +type Stack interface { + // Push 元素入栈 + Push(num int) + // Peek 访问栈顶元素 + Peek() int + // Pop 元素出栈 + Pop() int + // Size 栈的长度 + Size() int + // IsEmpty 栈是否为空 + IsEmpty() bool +} diff --git a/codes/go/chapter_stack_and_queue/stack_test.go b/codes/go/chapter_stack_and_queue/stack_test.go new file mode 100644 index 0000000..b3cd3da --- /dev/null +++ b/codes/go/chapter_stack_and_queue/stack_test.go @@ -0,0 +1,93 @@ +// File: stack_test.go +// Created Time: 2022-11-28 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +import "testing" + +func TestStack(t *testing.T) { + // 初始化栈 + stack := NewLinkedListStack() + + // 元素入栈 + stack.Push(1) + stack.Push(2) + stack.Push(3) + stack.Push(4) + stack.Push(5) + t.Log("栈 stack = ", stack.toString()) + + // 访问栈顶元素 + peek := stack.Peek() + t.Log("栈顶元素 peek = ", peek) + + // 元素出栈 + pop := stack.Pop() + t.Log("出栈元素 pop = ", pop, ", 出栈后 stack =", stack.toString()) + + // 获取栈的长度 + size := stack.Size() + t.Log("栈的长度 size = ", size) + + // 判断是否为空 + isEmpty := stack.IsEmpty() + t.Log("栈是否为空 = ", isEmpty) +} + +func TestArrayStack(t *testing.T) { + // 初始化栈 + stack := NewArrayStack() + + // 元素入栈 + stack.Push(1) + stack.Push(2) + stack.Push(3) + stack.Push(4) + stack.Push(5) + t.Log("栈 stack = ", stack.toString()) + + // 访问栈顶元素 + peek := stack.Peek() + t.Log("栈顶元素 peek = ", peek) + + // 元素出栈 + pop := stack.Pop() + t.Log("出栈元素 pop = ", pop, ", 出栈后 stack =", stack.toString()) + + // 获取栈的长度 + size := stack.Size() + t.Log("栈的长度 size = ", size) + + // 判断是否为空 + isEmpty := stack.IsEmpty() + t.Log("栈是否为空 = ", isEmpty) +} + +func TestLinkedListStack(t *testing.T) { + +} + +// BenchmarkStack 65.02 ns/op in Mac M1 Pro +func BenchmarkStack(b *testing.B) { + stack := NewLinkedListStack() + // use b.N for looping + for i := 0; i < b.N; i++ { + stack.Push(777) + } + for i := 0; i < b.N; i++ { + stack.Pop() + } +} + +// BenchmarkArrayStack 8 ns/op in Mac M1 Pro +func BenchmarkArrayStack(b *testing.B) { + stack := NewArrayStack() + // use b.N for looping + for i := 0; i < b.N; i++ { + stack.Push(777) + } + for i := 0; i < b.N; i++ { + stack.Pop() + } +}