Go 算法和数据结构
刷题过程中会遇到一些通用数据结构的封装,在这里记录一下。注意因为是刷算法题用的,没有考虑 goroutine 安全, 不要直接用在并发环境,如果是在生产环境中使用请加锁改造。(没有泛型写起来挺繁琐的)
Stack
type Stack struct {
st []int
}
func NewStack() *Stack {
return &Stack{st:make([]int,0)}
}
func (s *Stack) Push(x int) {
s.st = append(s.st, x)
}
func (s *Stack) Peek() int{
return s.st[len(s.st)-1]
}
func (s *Stack) Pop() int{
n := len(s.st)
top := s.st[n-1]
s.st = s.st[:n-1]
return top
}
func (s *Stack) Empty() bool{
return len(s.st) == 0
}
Queue
type Item struct {
Num int
Order int
}
type Queue struct {
items []Item
}
func NewQueue() *Queue {
return &Queue{
items: make([]Item, 0),
}
}
func (q *Queue) Push(x Item) {
q.items = append(q.items, x)
}
func (q *Queue) Pop() Item {
x := q.items[0]
q.items = q.items[1:]
return x
}
func (q *Queue) Front() Item {
return q.items[0]
}
func (q *Queue) End() Item {
return q.items[len(q.items)-1]
}
func (q *Queue) Empty() bool {
return len(q.items) == 0
}
Deque
import (
"container/list"
"fmt"
)
// 滑动窗口最大值
type Deque struct {
ll *list.List
}
func NewDeque() *Deque {
return &Deque{ll: list.New()}
}
func (dq *Deque) PushFront(x int) {
dq.ll.PushFront(x)
}
func (dq *Deque) PushBack(x int) {
dq.ll.PushBack(x)
}
func (dq *Deque) Pop() { // remove back
dq.ll.Remove(dq.ll.Back())
}
func (dq *Deque) PopFront() { // remove first
dq.ll.Remove(dq.ll.Front())
}
func (dq *Deque) Front() int {
return dq.ll.Front().Value.(int)
}
func (dq *Deque) Back() int {
return dq.ll.Back().Value.(int)
}
func (dq *Deque) Len() int {
return dq.ll.Len()
}
Linked List
package main
import "fmt"
// 测试链表。在 redigo 里边使用到了链表作为 pool 的实现
type IntList struct {
count int
// front,back 分别指向第一个和最后一个 node,或者是 nil。front.prev back.next 都是空
front, back *Node
}
// 链表节点
type Node struct {
next, prev *Node
}
func (l *IntList) Count() int {
return l.count
}
func (l *IntList) pushFront(node *Node) {
node.next = l.front
node.prev = nil
if l.count == 0 { // note when list is empty
l.back = node
} else {
l.front.prev = node
}
l.front = node
l.count++
}
func (l *IntList) popFront() {
first := l.front
l.count--
if l.count == 0 {
l.front, l.back = nil, nil
} else {
first.next.prev = nil
l.front = first.next
}
first.next, first.prev = nil, nil // clear first
}
func (l *IntList) popBack() {
last := l.back
l.count--
if l.count == 0 {
l.front, l.back = nil, nil
} else {
last.prev.next = nil
l.back = last.prev
}
last.prev, last.next = nil, nil
}
func (l *IntList) Print() {
cur := l.front
for cur != l.back {
fmt.Println(cur)
cur = cur.next
}
if l.back != nil {
fmt.Println(l.back)
}
}
Trie
// Package main provides ...
package main
import "fmt"
// https://golangbyexample.com/trie-implementation-in-go/
const (
ALBHABET_SIZE = 26
)
type node struct {
childrens [ALBHABET_SIZE]*node
isWordEnd bool
}
type trie struct {
root *node
}
func newTrie() *trie {
return &trie{
root: &node{},
}
}
func (t *trie) insert(word string) {
wordLength := len(word)
current := t.root
for i := 0; i < wordLength; i++ {
idx := word[i] - 'a'
if current.childrens[idx] == nil {
current.childrens[idx] = &node{}
}
current = current.childrens[idx]
}
current.isWordEnd = true
}
func (t *trie) find(word string) bool {
wordLength := len(word)
current := t.root
for i := 0; i < wordLength; i++ {
idx := word[i] - 'a'
if current.childrens[idx] == nil {
return false
}
current = current.childrens[idx]
}
if current.isWordEnd {
return true
}
return false
}
func main() {
trie := newTrie()
words := []string{"zhang", "wang", "li", "zhao"}
for i := 0; i < len(words); i++ {
trie.insert(words[i])
}
toFind := []string{"zhang", "wang", "li", "zhao", "gong"}
for i := 0; i < len(toFind); i++ {
c := toFind[i]
if trie.find(c) {
fmt.Printf("word[%s] found in trie.\n", c)
} else {
fmt.Printf("word[%s] not found in trie\n", c)
}
}
}
OrderedMap (类似 python collections.OrderedDict)
模拟 python collections.OrderedDict 写的,可以方便的实现 lru 等
package main
import (
"container/list"
"fmt"
)
// 按照 key 插入顺序遍历 map,类似 python collections.OrderedDict。注意不是 key 的字典序,而是插入顺序
type OrderedMap struct {
m map[string]int
me map[string]*list.Element
ll *list.List // 记录 key order
}
func NewOrderedMap() *OrderedMap {
return &OrderedMap{
m: make(map[string]int),
me: make(map[string]*list.Element),
ll: list.New(),
}
}
func (o *OrderedMap) Set(k string, v int) {
if _, found := o.m[k]; !found {
e := o.ll.PushBack(k)
o.me[k] = e
}
o.m[k] = v
}
func (o *OrderedMap) Exist(k string) bool {
_, found := o.m[k]
return found
}
func (o *OrderedMap) Get(k string) int {
return o.m[k]
}
func (o *OrderedMap) Delete(k string) {
delete(o.m, k)
node := o.me[k]
o.ll.Remove(node)
delete(o.me, k)
}
func (o *OrderedMap) Len() int {
return len(o.m)
}
// 按照 key 进入顺序返回
func (o *OrderedMap) Keys() []string {
keys := make([]string, o.ll.Len())
i := 0
for e := o.ll.Front(); e != nil; e = e.Next() {
keys[i] = e.Value.(string)
i++
}
return keys
}
当前内容版权归 PegasusWang 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 PegasusWang .