From 67409cdb12dd39b27b8f358b95ab44ba1af4097f Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Tue, 29 Nov 2022 00:48:01 +0800 Subject: [PATCH 1/7] fix(tree): amend tree in golang --- codes/go/chapter_tree/binary_search_tree.go | 3 ++- codes/go/chapter_tree/binary_tree_bfs.go | 1 + codes/go/chapter_tree/binary_tree_test.go | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/codes/go/chapter_tree/binary_search_tree.go b/codes/go/chapter_tree/binary_search_tree.go index 26eb94d..ac14e79 100644 --- a/codes/go/chapter_tree/binary_search_tree.go +++ b/codes/go/chapter_tree/binary_search_tree.go @@ -5,8 +5,9 @@ package chapter_tree import ( - . "github.com/krahets/hello-algo/pkg" "sort" + + . "github.com/krahets/hello-algo/pkg" ) type BinarySearchTree struct { diff --git a/codes/go/chapter_tree/binary_tree_bfs.go b/codes/go/chapter_tree/binary_tree_bfs.go index d04102f..5c07a96 100644 --- a/codes/go/chapter_tree/binary_tree_bfs.go +++ b/codes/go/chapter_tree/binary_tree_bfs.go @@ -6,6 +6,7 @@ package chapter_tree import ( "container/list" + . "github.com/krahets/hello-algo/pkg" ) diff --git a/codes/go/chapter_tree/binary_tree_test.go b/codes/go/chapter_tree/binary_tree_test.go index 2c05076..03a8553 100644 --- a/codes/go/chapter_tree/binary_tree_test.go +++ b/codes/go/chapter_tree/binary_tree_test.go @@ -5,8 +5,9 @@ package chapter_tree import ( - . "github.com/krahets/hello-algo/pkg" "testing" + + . "github.com/krahets/hello-algo/pkg" ) func TestBinaryTree(t *testing.T) { 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 2/7] 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() + } +} From 76a7e0b2325b66b4749394da03de95f673824e00 Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Tue, 29 Nov 2022 01:10:22 +0800 Subject: [PATCH 3/7] feat(queue): implement queue in golang code --- .../go/chapter_stack_and_queue/array_queue.go | 92 +++++++++++++++++++ .../linkedlist_queue.go | 79 ++++++++++++++++ codes/go/chapter_stack_and_queue/queue.go | 18 ++++ .../go/chapter_stack_and_queue/queue_test.go | 91 ++++++++++++++++++ 4 files changed, 280 insertions(+) create mode 100644 codes/go/chapter_stack_and_queue/array_queue.go create mode 100644 codes/go/chapter_stack_and_queue/linkedlist_queue.go create mode 100644 codes/go/chapter_stack_and_queue/queue.go create mode 100644 codes/go/chapter_stack_and_queue/queue_test.go diff --git a/codes/go/chapter_stack_and_queue/array_queue.go b/codes/go/chapter_stack_and_queue/array_queue.go new file mode 100644 index 0000000..f771ea2 --- /dev/null +++ b/codes/go/chapter_stack_and_queue/array_queue.go @@ -0,0 +1,92 @@ +// File: array_queue.go +// Created Time: 2022-11-28 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +import ( + "fmt" + "strings" +) + +// ArrayQueue 基于环形数组实现的队列, 不支持扩容 +type ArrayQueue struct { + data []any // 用于存储队列元素的数组 + capacity int // 队列容量(即最多容量的元素个数) + head int // 头指针,指向队首 + tail int // 尾指针,指向队尾 + 1 +} + +// NewArrayQueue 基于环形数组实现的队列 +func NewArrayQueue(capacity int) *ArrayQueue { + return &ArrayQueue{ + data: make([]any, capacity), + capacity: capacity, + head: 0, + tail: 0, + } +} + +// Size 获取队列的长度 +func (q *ArrayQueue) Size() int { + size := (q.capacity + q.tail - q.head) % q.capacity + return size +} + +// IsEmpty 判断队列是否为空 +func (q *ArrayQueue) IsEmpty() bool { + return q.tail-q.head == 0 +} + +// Offer 入队 +func (q *ArrayQueue) Offer(v any) { + // 当 tail == capacity 表示队列已满 + if q.Size() == q.capacity { + return + } + // 尾结点后添加 + q.data[q.tail] = v + // 尾指针向后移动一位,越过尾部后返回到数组头部 + q.tail = (q.tail + 1) % q.capacity +} + +// Poll 出队 +func (q *ArrayQueue) Poll() any { + if q.IsEmpty() { + return nil + } + v := q.data[q.head] + // 队头指针向后移动,越过尾部后返回到数组头部 + q.head = (q.head + 1) % q.capacity + return v +} + +// Peek 访问队首元素 +func (q *ArrayQueue) Peek() any { + if q.IsEmpty() { + return nil + } + v := q.data[q.head] + return v +} + +func (q *ArrayQueue) Print() { + fmt.Println(q.toString()) +} + +// toString 通过字符串的方式输出 +func (q *ArrayQueue) toString() string { + // 为空时 + if q.IsEmpty() { + return "empty items" + } + var builder strings.Builder + size := q.Size() + str := fmt.Sprintf("%+v", q.data[q.head]) + for i := 1; i < size; i++ { + builder.WriteString(str + " -> ") + str = fmt.Sprintf("%+v", q.data[(i+q.head)%q.capacity]) + } + builder.WriteString(str) + return builder.String() +} diff --git a/codes/go/chapter_stack_and_queue/linkedlist_queue.go b/codes/go/chapter_stack_and_queue/linkedlist_queue.go new file mode 100644 index 0000000..6c71f6f --- /dev/null +++ b/codes/go/chapter_stack_and_queue/linkedlist_queue.go @@ -0,0 +1,79 @@ +// File: linkedlist_queue.go +// Created Time: 2022-11-28 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +import ( + "container/list" + "fmt" + "strings" +) + +// LinkedListQueue 基于链表实现的栈, 使用内置包 list 来实现栈 +type LinkedListQueue struct { + list *list.List +} + +// NewLinkedListQueue 初始化链表 +func NewLinkedListQueue() *LinkedListQueue { + return &LinkedListQueue{ + list: list.New(), + } +} + +// Offer 入队 +func (s *LinkedListQueue) Offer(value any) { + s.list.PushBack(value) +} + +// Poll 出队 +func (s *LinkedListQueue) Poll() any { + if s.IsEmpty() { + return nil + } + e := s.list.Front() + s.list.Remove(e) + return e.Value +} + +// Peek 访问队首元素 +func (s *LinkedListQueue) Peek() any { + if s.IsEmpty() { + return nil + } + e := s.list.Front() + return e.Value +} + +// Size 获取队列的长度 +func (s *LinkedListQueue) Size() int { + return s.list.Len() +} + +// IsEmpty 判断队列是否为空 +func (s *LinkedListQueue) IsEmpty() bool { + return s.list.Len() == 0 +} + +func (s *LinkedListQueue) Print() { + fmt.Println(s.toString()) +} + +func (s *LinkedListQueue) toString() any { + var builder strings.Builder + if s.IsEmpty() { + fmt.Println("empty stack") + return nil + } + e := s.list.Front() + // 强转为 string, 会影响效率 + str := fmt.Sprintf("%v", e.Value) + for e.Next() != nil { + builder.WriteString(str + " -> ") + e = e.Next() + str = fmt.Sprintf("%v", e.Value) + } + builder.WriteString(str) + return builder.String() +} diff --git a/codes/go/chapter_stack_and_queue/queue.go b/codes/go/chapter_stack_and_queue/queue.go new file mode 100644 index 0000000..c8f16c8 --- /dev/null +++ b/codes/go/chapter_stack_and_queue/queue.go @@ -0,0 +1,18 @@ +// File: queue.go +// Created Time: 2022-11-29 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +type Queue interface { + // Offer 元素入队 + Offer(num int) + // Peek 访问首元素 + Peek() int + // Poll 元素出队 + Poll() int + // Size 获取队列长度 + Size() int + // IsEmpty 队列是否为空 + IsEmpty() bool +} diff --git a/codes/go/chapter_stack_and_queue/queue_test.go b/codes/go/chapter_stack_and_queue/queue_test.go new file mode 100644 index 0000000..f4734a5 --- /dev/null +++ b/codes/go/chapter_stack_and_queue/queue_test.go @@ -0,0 +1,91 @@ +// File: queue_test.go +// Created Time: 2022-11-28 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +import "testing" + +func TestArrayQueue(t *testing.T) { + // 初始化队 + capacity := 10 + queue := NewArrayQueue(capacity) + + // 元素入队 + queue.Offer(1) + queue.Offer(2) + queue.Offer(3) + queue.Offer(4) + queue.Offer(5) + t.Log("队列 queue = ", queue.toString()) + + // 访问队首元素 + peek := queue.Peek() + t.Log("队首元素 peek = ", peek) + + // 元素出队 + pop := queue.Poll() + t.Log("出队元素 pop = ", pop, ", 出队后 queue =", queue.toString()) + + // 获取队的长度 + size := queue.Size() + t.Log("队的长度 size = ", size) + + // 判断是否为空 + isEmpty := queue.IsEmpty() + t.Log("队是否为空 = ", isEmpty) +} + +func TestLinkedListQueue(t *testing.T) { + // 初始化队 + queue := NewLinkedListQueue() + + // 元素入队 + queue.Offer(1) + queue.Offer(2) + queue.Offer(3) + queue.Offer(4) + queue.Offer(5) + t.Log("队列 queue = ", queue.toString()) + + // 访问队首元素 + peek := queue.Peek() + t.Log("队首元素 peek = ", peek) + + // 元素出队 + pop := queue.Poll() + t.Log("出队元素 pop = ", pop, ", 出队后 queue =", queue.toString()) + + // 获取队的长度 + size := queue.Size() + t.Log("队的长度 size = ", size) + + // 判断是否为空 + isEmpty := queue.IsEmpty() + t.Log("队是否为空 = ", isEmpty) +} + +// BenchmarkArrayQueue 8 ns/op in Mac M1 Pro +func BenchmarkArrayQueue(b *testing.B) { + capacity := 1000 + stack := NewArrayQueue(capacity) + // use b.N for looping + for i := 0; i < b.N; i++ { + stack.Offer(777) + } + for i := 0; i < b.N; i++ { + stack.Poll() + } +} + +// BenchmarkLinkedQueue 62.66 ns/op in Mac M1 Pro +func BenchmarkLinkedQueue(b *testing.B) { + stack := NewLinkedListQueue() + // use b.N for looping + for i := 0; i < b.N; i++ { + stack.Offer(777) + } + for i := 0; i < b.N; i++ { + stack.Poll() + } +} From bed8b07b0b3c9c27198ff9e89c297883a7f4d4ff Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Tue, 29 Nov 2022 01:10:51 +0800 Subject: [PATCH 4/7] feat(deeue): implement deque in golang code --- codes/go/chapter_stack_and_queue/deque.go | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 codes/go/chapter_stack_and_queue/deque.go diff --git a/codes/go/chapter_stack_and_queue/deque.go b/codes/go/chapter_stack_and_queue/deque.go new file mode 100644 index 0000000..fb419a6 --- /dev/null +++ b/codes/go/chapter_stack_and_queue/deque.go @@ -0,0 +1,27 @@ +// File: deque.go +// Created Time: 2022-11-29 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +type Deque interface { + // OfferFirst 元素入队 + OfferFirst(num int) + // OfferLast 元素入队 + OfferLast(num int) + + // PeekFirst 访问首元素 + PeekFirst() int + // PeekLast 访问尾元素 + PeekLast() int + + // PollFirst 元素出队 + PollFirst() int + // PollLast 元素出队 + PollLast() int + + // Size 获取队列长度 + Size() int + // IsEmpty 队列是否为空 + IsEmpty() bool +} From d32f15feb14a19e2f1fc0c125795ef87e8cdfc6a Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Tue, 29 Nov 2022 01:17:07 +0800 Subject: [PATCH 5/7] fix(testcase): modify testcase --- .../go/chapter_stack_and_queue/stack_test.go | 78 +++++++++---------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/codes/go/chapter_stack_and_queue/stack_test.go b/codes/go/chapter_stack_and_queue/stack_test.go index b3cd3da..b546d55 100644 --- a/codes/go/chapter_stack_and_queue/stack_test.go +++ b/codes/go/chapter_stack_and_queue/stack_test.go @@ -6,35 +6,6 @@ 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() @@ -65,19 +36,32 @@ func TestArrayStack(t *testing.T) { } 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() - } + + // 元素入栈 + 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) } // BenchmarkArrayStack 8 ns/op in Mac M1 Pro @@ -91,3 +75,15 @@ func BenchmarkArrayStack(b *testing.B) { stack.Pop() } } + +// BenchmarkLinkedListStack 65.02 ns/op in Mac M1 Pro +func BenchmarkLinkedListStack(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() + } +} From 19469aecbfbd2422a1da0452551f2e99ff3002d9 Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Tue, 29 Nov 2022 10:42:09 +0800 Subject: [PATCH 6/7] fix(go): modify interface of stack, queue and deque --- codes/go/chapter_stack_and_queue/deque.go | 17 ++++++++--------- .../chapter_stack_and_queue/linkedlist_queue.go | 5 ++--- .../chapter_stack_and_queue/linkedlist_stack.go | 5 ++--- codes/go/chapter_stack_and_queue/queue.go | 8 +++++--- codes/go/chapter_stack_and_queue/queue_test.go | 9 ++++++--- codes/go/chapter_stack_and_queue/stack.go | 6 ++++-- codes/go/chapter_stack_and_queue/stack_test.go | 9 +++++---- 7 files changed, 32 insertions(+), 27 deletions(-) diff --git a/codes/go/chapter_stack_and_queue/deque.go b/codes/go/chapter_stack_and_queue/deque.go index fb419a6..3ac070e 100644 --- a/codes/go/chapter_stack_and_queue/deque.go +++ b/codes/go/chapter_stack_and_queue/deque.go @@ -6,22 +6,21 @@ package chapter_stack_and_queue type Deque interface { // OfferFirst 元素入队 - OfferFirst(num int) + OfferFirst(num any) // OfferLast 元素入队 - OfferLast(num int) - + OfferLast(num any) // PeekFirst 访问首元素 - PeekFirst() int + PeekFirst() any // PeekLast 访问尾元素 - PeekLast() int - + PeekLast() any // PollFirst 元素出队 - PollFirst() int + PollFirst() any // PollLast 元素出队 - PollLast() int - + PollLast() any // Size 获取队列长度 Size() int // IsEmpty 队列是否为空 IsEmpty() bool + // toString 队列输出为字符串 + toString() string } diff --git a/codes/go/chapter_stack_and_queue/linkedlist_queue.go b/codes/go/chapter_stack_and_queue/linkedlist_queue.go index 6c71f6f..5b62ac3 100644 --- a/codes/go/chapter_stack_and_queue/linkedlist_queue.go +++ b/codes/go/chapter_stack_and_queue/linkedlist_queue.go @@ -10,7 +10,7 @@ import ( "strings" ) -// LinkedListQueue 基于链表实现的栈, 使用内置包 list 来实现栈 +// LinkedListQueue 基于链表实现的队列, 使用内置包 list 来实现栈 type LinkedListQueue struct { list *list.List } @@ -60,11 +60,10 @@ func (s *LinkedListQueue) Print() { fmt.Println(s.toString()) } -func (s *LinkedListQueue) toString() any { +func (s *LinkedListQueue) toString() string { var builder strings.Builder if s.IsEmpty() { fmt.Println("empty stack") - return nil } e := s.list.Front() // 强转为 string, 会影响效率 diff --git a/codes/go/chapter_stack_and_queue/linkedlist_stack.go b/codes/go/chapter_stack_and_queue/linkedlist_stack.go index 88fe4dc..24f46ac 100644 --- a/codes/go/chapter_stack_and_queue/linkedlist_stack.go +++ b/codes/go/chapter_stack_and_queue/linkedlist_stack.go @@ -23,7 +23,7 @@ func NewLinkedListStack() *LinkedListStack { } // Push 入栈 -func (s *LinkedListStack) Push(value any) { +func (s *LinkedListStack) Push(value int) { s.list.PushBack(value) } @@ -60,11 +60,10 @@ func (s *LinkedListStack) Print() { fmt.Println(s.toString()) } -func (s *LinkedListStack) toString() any { +func (s *LinkedListStack) toString() string { var builder strings.Builder if s.IsEmpty() { fmt.Println("empty stack") - return nil } e := s.list.Back() // 强转为 string, 会影响效率 diff --git a/codes/go/chapter_stack_and_queue/queue.go b/codes/go/chapter_stack_and_queue/queue.go index c8f16c8..03b97e5 100644 --- a/codes/go/chapter_stack_and_queue/queue.go +++ b/codes/go/chapter_stack_and_queue/queue.go @@ -6,13 +6,15 @@ package chapter_stack_and_queue type Queue interface { // Offer 元素入队 - Offer(num int) + Offer(num any) // Peek 访问首元素 - Peek() int + Peek() any // Poll 元素出队 - Poll() int + Poll() any // Size 获取队列长度 Size() int // IsEmpty 队列是否为空 IsEmpty() bool + // toString 队列输出为字符串 + toString() string } diff --git a/codes/go/chapter_stack_and_queue/queue_test.go b/codes/go/chapter_stack_and_queue/queue_test.go index f4734a5..996b0bc 100644 --- a/codes/go/chapter_stack_and_queue/queue_test.go +++ b/codes/go/chapter_stack_and_queue/queue_test.go @@ -7,9 +7,11 @@ package chapter_stack_and_queue import "testing" func TestArrayQueue(t *testing.T) { - // 初始化队 + + // 初始化队列,使用队列的通用接口 + var queue Queue capacity := 10 - queue := NewArrayQueue(capacity) + queue = NewArrayQueue(capacity) // 元素入队 queue.Offer(1) @@ -38,7 +40,8 @@ func TestArrayQueue(t *testing.T) { func TestLinkedListQueue(t *testing.T) { // 初始化队 - queue := NewLinkedListQueue() + var queue Queue + queue = NewLinkedListQueue() // 元素入队 queue.Offer(1) diff --git a/codes/go/chapter_stack_and_queue/stack.go b/codes/go/chapter_stack_and_queue/stack.go index 7215224..7795387 100644 --- a/codes/go/chapter_stack_and_queue/stack.go +++ b/codes/go/chapter_stack_and_queue/stack.go @@ -8,11 +8,13 @@ type Stack interface { // Push 元素入栈 Push(num int) // Peek 访问栈顶元素 - Peek() int + Peek() any // Pop 元素出栈 - Pop() int + Pop() any // Size 栈的长度 Size() int // IsEmpty 栈是否为空 IsEmpty() bool + // toString 栈输出为字符串 + toString() string } diff --git a/codes/go/chapter_stack_and_queue/stack_test.go b/codes/go/chapter_stack_and_queue/stack_test.go index b546d55..95c6d24 100644 --- a/codes/go/chapter_stack_and_queue/stack_test.go +++ b/codes/go/chapter_stack_and_queue/stack_test.go @@ -7,8 +7,9 @@ package chapter_stack_and_queue import "testing" func TestArrayStack(t *testing.T) { - // 初始化栈 - stack := NewArrayStack() + // 初始化栈, 使用接口承接 + var stack Stack + stack = NewArrayStack() // 元素入栈 stack.Push(1) @@ -37,8 +38,8 @@ func TestArrayStack(t *testing.T) { func TestLinkedListStack(t *testing.T) { // 初始化栈 - stack := NewLinkedListStack() - + var stack Stack + stack = NewLinkedListStack() // 元素入栈 stack.Push(1) stack.Push(2) From a554590fa81b75ce156121aae74619d1a998d430 Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Tue, 29 Nov 2022 10:43:47 +0800 Subject: [PATCH 7/7] feat(deque): add implementation of deque --- .../go/chapter_stack_and_queue/deque_test.go | 53 +++++++++ .../linkedlist_deque.go | 102 ++++++++++++++++++ .../go/chapter_stack_and_queue/queue_test.go | 1 - 3 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 codes/go/chapter_stack_and_queue/deque_test.go create mode 100644 codes/go/chapter_stack_and_queue/linkedlist_deque.go diff --git a/codes/go/chapter_stack_and_queue/deque_test.go b/codes/go/chapter_stack_and_queue/deque_test.go new file mode 100644 index 0000000..c0eaf08 --- /dev/null +++ b/codes/go/chapter_stack_and_queue/deque_test.go @@ -0,0 +1,53 @@ +// File: deque_test.go +// Created Time: 2022-11-29 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +import "testing" + +func TestLinkedListDeque(t *testing.T) { + // 初始化队列 + var deque Deque + deque = NewLinkedListDeque() + + // 元素入队 + deque.OfferLast(2) + deque.OfferLast(5) + deque.OfferLast(4) + deque.OfferFirst(3) + deque.OfferFirst(1) + t.Log("队列 deque = ", deque.toString()) + + // 访问队首元素 + peekFirst := deque.PeekFirst() + t.Log("队首元素 peek = ", peekFirst) + peekLast := deque.PeekLast() + t.Log("队尾元素 peek = ", peekLast) + + // 元素出队 + pollFirst := deque.PollFirst() + t.Log("队首出队元素 pollFirst = ", pollFirst, ",队首出队后 deque = ", deque.toString()) + pollLast := deque.PollLast() + t.Log("队尾出队元素 pollLast = ", pollLast, ",队尾出队后 deque = ", deque.toString()) + + // 获取队的长度 + size := deque.Size() + t.Log("队的长度 size = ", size) + + // 判断是否为空 + isEmpty := deque.IsEmpty() + t.Log("队是否为空 = ", isEmpty) +} + +// BenchmarkArrayQueue 67.92 ns/op in Mac M1 Pro +func BenchmarkLinkedListDeque(b *testing.B) { + stack := NewLinkedListDeque() + // use b.N for looping + for i := 0; i < b.N; i++ { + stack.OfferLast(777) + } + for i := 0; i < b.N; i++ { + stack.PollFirst() + } +} diff --git a/codes/go/chapter_stack_and_queue/linkedlist_deque.go b/codes/go/chapter_stack_and_queue/linkedlist_deque.go new file mode 100644 index 0000000..62a6149 --- /dev/null +++ b/codes/go/chapter_stack_and_queue/linkedlist_deque.go @@ -0,0 +1,102 @@ +// File: linkedlist_deque.go +// Created Time: 2022-11-29 +// Author: Reanon (793584285@qq.com) + +package chapter_stack_and_queue + +import ( + "container/list" + "fmt" + "strings" +) + +// LinkedListDeque 基于链表实现的双端队列, 使用内置包 list 来实现栈 +type LinkedListDeque struct { + list *list.List +} + +// NewLinkedListDeque 初始化双端队列 +func NewLinkedListDeque() *LinkedListDeque { + return &LinkedListDeque{ + list: list.New(), + } +} + +// OfferFirst 元素入队 +func (s *LinkedListDeque) OfferFirst(value any) { + s.list.PushFront(value) +} + +// OfferLast 元素入队 +func (s *LinkedListDeque) OfferLast(value any) { + s.list.PushBack(value) +} + +// PollFirst 元素出队 +func (s *LinkedListDeque) PollFirst() any { + if s.IsEmpty() { + return nil + } + e := s.list.Front() + s.list.Remove(e) + return e.Value +} + +// PollLast 元素出队 +func (s *LinkedListDeque) PollLast() any { + if s.IsEmpty() { + return nil + } + e := s.list.Back() + s.list.Remove(e) + return e.Value +} + +// PeekFirst 访问首元素 +func (s *LinkedListDeque) PeekFirst() any { + if s.IsEmpty() { + return nil + } + e := s.list.Front() + return e.Value +} + +// PeekLast 访问尾元素 +func (s *LinkedListDeque) PeekLast() any { + if s.IsEmpty() { + return nil + } + e := s.list.Back() + return e.Value +} + +// Size 获取队列的长度 +func (s *LinkedListDeque) Size() int { + return s.list.Len() +} + +// IsEmpty 判断队列是否为空 +func (s *LinkedListDeque) IsEmpty() bool { + return s.list.Len() == 0 +} + +func (s *LinkedListDeque) Print() { + fmt.Println(s.toString()) +} + +func (s *LinkedListDeque) toString() string { + var builder strings.Builder + if s.IsEmpty() { + fmt.Println("empty stack") + } + e := s.list.Front() + // 强转为 string, 会影响效率 + str := fmt.Sprintf("%v", e.Value) + for e.Next() != nil { + builder.WriteString(str + " -> ") + e = e.Next() + str = fmt.Sprintf("%v", e.Value) + } + builder.WriteString(str) + return builder.String() +} diff --git a/codes/go/chapter_stack_and_queue/queue_test.go b/codes/go/chapter_stack_and_queue/queue_test.go index 996b0bc..e8c74ec 100644 --- a/codes/go/chapter_stack_and_queue/queue_test.go +++ b/codes/go/chapter_stack_and_queue/queue_test.go @@ -7,7 +7,6 @@ package chapter_stack_and_queue import "testing" func TestArrayQueue(t *testing.T) { - // 初始化队列,使用队列的通用接口 var queue Queue capacity := 10