-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(stack_and_queue): add go code. #45
Merged
krahets
merged 7 commits into
krahets:master
from
Reanon:feature/support-go-chapter-stack-queue
Nov 29, 2022
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
67409cd
fix(tree): amend tree in golang
Reanon 27e4402
feat(stack): implement stack in golang code
Reanon 76a7e0b
feat(queue): implement queue in golang code
Reanon bed8b07
feat(deeue): implement deque in golang code
Reanon d32f15f
fix(testcase): modify testcase
Reanon 19469ae
fix(go): modify interface of stack, queue and deque
Reanon a554590
feat(deque): add implementation of deque
Reanon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// File: deque.go | ||
// Created Time: 2022-11-29 | ||
// Author: Reanon (793584285@qq.com) | ||
|
||
package chapter_stack_and_queue | ||
|
||
type Deque interface { | ||
// OfferFirst 元素入队 | ||
OfferFirst(num any) | ||
// OfferLast 元素入队 | ||
OfferLast(num any) | ||
// PeekFirst 访问首元素 | ||
PeekFirst() any | ||
// PeekLast 访问尾元素 | ||
PeekLast() any | ||
// PollFirst 元素出队 | ||
PollFirst() any | ||
// PollLast 元素出队 | ||
PollLast() any | ||
// Size 获取队列长度 | ||
Size() int | ||
// IsEmpty 队列是否为空 | ||
IsEmpty() bool | ||
// toString 队列输出为字符串 | ||
toString() string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Testing for the Go built-in deque is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you use
interface
to reveal the usage of built-in Stack, Queue, and Deque?I'm wondering if it is the only way as It is not consistent with other languages.