栈的定义

栈是一种基于线性表实现的数据结构,特性是先进后出。先进入栈的元素后出来。
结构体定义
先定义栈的接口 Stack:
// 栈的接口
type Stack[T any] interface {
// 判空
IsEmpty() bool
// 返回大小
Size() int
// 压栈
Push(e T)
// 弹栈
Pop() T
// 返回栈顶
Peek() T
}
Stack 接口定义了栈有关的操作的方法。
顺序栈
ArrayStack 结构体是基于切片,其实也就是数组实现的栈。
package stack
import (
"fmt"
"strings"
)
// 使用数组实现的栈
type ArrayStack[T any] struct {
values []T
}
func NewArrayStack[T any]() *ArrayStack[T] {
return &ArrayStack[T]{values: make([]T, 0, 10)}
}
func (a *ArrayStack[T]) String() string {
if l.head == nil {
return "<nil>"
}
var ans strings.Builder
ans.WriteString("[")
for i, value := range a.values {
if i+1 == len(a.values) {
ans.WriteString(fmt.Sprintf("%v", value))
break
}
ans.WriteString(fmt.Sprintf("%v, ", value))
}
ans.WriteString("]")
return ans.String()
}
func (a *ArrayStack[T]) IsEmpty() bool {
return len(a.values) == 0
}
func (a *ArrayStack[T]) Size() int {
return len(a.values)
}
func (a *ArrayStack[T]) Push(e T) {
a.values = append(a.values, e)
}
func (a *ArrayStack[T]) Pop() T {
i := len(a.values) - 1
ans := a.values[i]
a.values = a.values[:i]
return ans
}
func (a *ArrayStack[T]) Peek() T {
return a.values[len(a.values)-1]
}
写一个测试用例:
func TestArrayStack(t *testing.T) {
stack := NewArrayStack[int]()
fmt.Printf("stack is empty: %v\n", stack.IsEmpty())
fmt.Println(stack)
stack.Push(5)
stack.Push(4)
stack.Push(3)
stack.Push(2)
stack.Push(1)
fmt.Println(stack)
fmt.Printf("stack is empty: %v\n", stack.IsEmpty())
fmt.Printf("stack's peek is: %v\n", stack.Peek())
fmt.Printf("stack's size is: %v\n", stack.Size())
fmt.Println("stack pops:")
for !stack.IsEmpty() {
fmt.Println(stack.Pop())
}
}
结果如下:

链式栈
LinkedStack 结构体是基于链表实现的栈。
package stack
import (
"fmt"
"strings"
"github.com/code-art/algorithm-go/list"
)
// 链式栈
type LinkedStack[T any] struct {
head *list.ListNode[T]
size int
}
func NewLinkedStack[T any]() *LinkedStack[T] {
return &LinkedStack[T]{}
}
func (l *LinkedStack[T]) String() string {
var ans strings.Builder
for p := l.head; p != nil; p = p.Next {
if p.Next == nil {
ans.WriteString(fmt.Sprintf("%v", p.Val))
break
}
ans.WriteString(fmt.Sprintf("%v->", p.Val))
}
return ans.String()
}
func (l *LinkedStack[T]) IsEmpty() bool {
return l.size == 0
}
func (l *LinkedStack[T]) Size() int {
return l.size
}
// 链式栈入栈操作相当于链表头插入
func (l *LinkedStack[T]) Push(e T) {
oldHead := l.head
l.head = &list.ListNode[T]{Val: e}
l.head.Next = oldHead
l.size++
}
func (l *LinkedStack[T]) Pop() T {
ans := l.head.Val
l.head = l.head.Next
l.size--
return ans
}
func (l *LinkedStack[T]) Peek() T {
return l.head.Val
}
写一个测试用例:
func TestLinkedStack(t *testing.T) {
stack := NewLinkedStack[int]()
fmt.Printf("stack is empty: %v\n", stack.IsEmpty())
fmt.Println(stack)
stack.Push(5)
stack.Push(4)
stack.Push(3)
stack.Push(2)
stack.Push(1)
fmt.Println(stack)
fmt.Printf("stack is empty: %v\n", stack.IsEmpty())
fmt.Printf("stack's peek is: %v\n", stack.Peek())
fmt.Printf("stack's size is: %v\n", stack.Size())
fmt.Println("stack pops:")
for !stack.IsEmpty() {
fmt.Println(stack.Pop())
}
}
结果如下:

队列的定义

队列是是一种先入先出的数据结构,先进入的元素先出去。
结构体定义
定义队列的接口 Queue:
// 队列的接口
type Queue[T any] interface {
IsEmpty() bool
Size() int
// 入队
Enqueue(e T)
// 出队
Dequeue() T
// 返回队头
Peek() T
}
顺序队列
package queue
import (
"fmt"
"strings"
)
type ArrayQueue[T any] struct {
values []T
}
func NewArrayQueue[T any]() *ArrayQueue[T] {
return &ArrayQueue[T]{values: make([]T, 0, 10)}
}
func (a *ArrayQueue[T]) String() string {
var ans strings.Builder
ans.WriteString("[")
for i, value := range a.values {
if i+1 == len(a.values) {
ans.WriteString(fmt.Sprintf("%v", value))
break
}
ans.WriteString(fmt.Sprintf("%v, ", value))
}
ans.WriteString("]")
return ans.String()
}
func (a *ArrayQueue[T]) IsEmpty() bool {
return len(a.values) == 0
}
func (a *ArrayQueue[T]) Size() int {
return len(a.values)
}
func (a *ArrayQueue[T]) Enqueue(e T) {
a.values = append(a.values, e)
}
func (a *ArrayQueue[T]) Dequeue() T {
ans := a.values[0]
a.values = a.values[1:]
return ans
}
func (a *ArrayQueue[T]) Peek() T {
return a.values[0]
}
单元测试:
func TestArrayQueue(t *testing.T) {
queue := NewArrayQueue[int]()
fmt.Println("queue is empty: ", queue.IsEmpty())
queue.Enqueue(5)
queue.Enqueue(4)
queue.Enqueue(3)
queue.Enqueue(2)
queue.Enqueue(1)
fmt.Println(queue)
fmt.Println("queue's peek is: ", queue.Peek())
fmt.Println("queue's size is: ", queue.Size())
fmt.Println("queue dequeues:")
for !queue.IsEmpty() {
fmt.Println(queue.Dequeue())
}
}

链式队列
package queue
import (
"fmt"
"strings"
"github.com/code-art/algorithm-go/list"
)
type LinkedQueue[T any] struct {
head *list.ListNode[T]
tail *list.ListNode[T]
size int
}
func NewLinkedQueue[T any]() *LinkedQueue[T] {
return &LinkedQueue[T]{}
}
func (l *LinkedQueue[T]) String() string {
var ans strings.Builder
for p := l.head; p != nil; p = p.Next {
if p.Next == nil {
ans.WriteString(fmt.Sprintf("%v", p.Val))
break
}
ans.WriteString(fmt.Sprintf("%v->", p.Val))
}
return ans.String()
}
func (l *LinkedQueue[T]) IsEmpty() bool {
return l.size == 0
}
func (l *LinkedQueue[T]) Size() int {
return l.size
}
func (l *LinkedQueue[T]) Enqueue(e T) {
newNode := &list.ListNode[T]{Val: e}
if l.head == nil {
l.head = newNode
l.tail = newNode
} else {
l.tail.Next = newNode
l.tail = newNode
}
l.size++
}
单元测试:
func TestLinkedQueue(t *testing.T) {
queue := NewLinkedQueue[int]()
fmt.Println("queue is empty: ", queue.IsEmpty())
queue.Enqueue(5)
queue.Enqueue(4)
queue.Enqueue(3)
queue.Enqueue(2)
queue.Enqueue(1)
fmt.Println(queue)
fmt.Println("queue's peek is: ", queue.Peek())
fmt.Println("queue's size is: ", queue.Size())
fmt.Println("queue dequeues:")
for !queue.IsEmpty() {
fmt.Println(queue.Dequeue())
}
}

环形队列
// 环形队列
type CircularQueue[T any] struct {
values []T
capacity int
size int
start int
end int
}
func NewCircularQueue[T any](values []T, capacity int) *CircularQueue[T] {
return &CircularQueue[T]{values: values, capacity: capacity}
}
func (c *CircularQueue[T]) IsEmpty() bool {
return c.size == 0
}
func (c *CircularQueue[T]) IsFull() bool {
return c.size == c.capacity
}
func (c *CircularQueue[T]) Size() int {
return c.size
}
func (c *CircularQueue[T]) Enqueue(e T) {
if c.IsFull() {
fmt.Println("Queue is full, can't enqueue.")
} else {
c.values[c.end] = e
if c.end == c.capacity-1 {
c.end = 0
} else {
c.end++
}
c.size++
}
}
func (c *CircularQueue[T]) Dequeue() T {
if c.IsEmpty() {
fmt.Println("Queue is empty, can't dequeue.")
return *new(T)
} else {
ans := c.values[c.start]
if c.start == c.capacity-1 {
c.start = 0
} else {
c.start++
}
c.size--
return ans
}
}
func (c *CircularQueue[T]) Peek() T {
if c.IsEmpty() {
fmt.Println("Queue is empty.")
return *new(T)
} else {
return c.values[c.start]
}
}
双端队列
// 双端队列
type Deque[T any] struct {
head *list.DoubleListNode[T]
tail *list.DoubleListNode[T]
size int
}
func NewDeque[T any](values []T) *Deque[T] {
node := list.CreateDoubleListNode(values)
p := node
for p.Next != nil {
p = p.Next
}
return &Deque[T]{head: node, tail: p, size: len(values)}
}
func (d *Deque[T]) String() string {
return d.head.String()
}
func (d *Deque[T]) IsEmpty() bool {
return d.size == 0
}
func (d *Deque[T]) Size() int {
return d.size
}
func (d *Deque[T]) Enqueue(e T) {
d.EnqueueTail(e)
}
func (d *Deque[T]) Dequeue() T {
return d.DequeueHead()
}
func (d *Deque[T]) Peek() T {
return d.PeekHead()
}
func (d *Deque[T]) EnqueueHead(e T) {
newNode := &list.DoubleListNode[T]{Val: e}
if d.head == nil {
d.head = newNode
d.tail = newNode
} else {
d.head.Prev = newNode
newNode.Next = d.head
d.head = newNode
}
d.size++
}
func (d *Deque[T]) EnqueueTail(e T) {
newNode := &list.DoubleListNode[T]{Val: e}
if d.head == nil {
d.head = newNode
d.tail = newNode
} else {
d.tail.Next = newNode
newNode.Prev = d.tail
d.tail = newNode
}
d.size++
}
func (d *Deque[T]) DequeueHead() T {
ans := d.head.Val
if d.head == d.tail {
d.head, d.tail = nil, nil
} else {
d.head = d.head.Next
d.head.Prev = nil
}
d.size--
return ans
}
func (d *Deque[T]) DequeueTail() T {
ans := d.tail.Val
if d.head == d.tail {
d.head, d.tail = nil, nil
} else {
d.tail = d.tail.Prev
d.tail.Next = nil
}
d.size--
return ans
}
func (d *Deque[T]) PeekHead() T {
return d.head.Val
}
func (d *Deque[T]) PeekTail() T {
return d.tail.Val
}