├── .gitignore ├── 01_list ├── 00_img │ └── 01_链表.drawio.svg ├── 01_list │ ├── list.go │ └── list_test.go ├── 02_lru │ ├── lru.go │ └── lru_test.go └── 03_q1_list_bug │ └── main.go ├── 02_array ├── 00_img │ ├── 01_array.drawio.svg │ └── 02_slice_struct.drawio.svg ├── 01_array_example │ └── main.go ├── 02_slice │ └── main.go └── 03_q1_slice_cap │ └── main.go ├── 03_stack ├── 00_img │ └── 01_stack.drawio.svg ├── 01_array_stack │ ├── stack.go │ └── stack_test.go ├── 02_list_stack │ ├── stack.go │ └── stack_test.go ├── 03_calculation │ ├── calculation.go │ ├── calculation_test.go │ ├── stack_int.go │ └── stack_string.go └── 04_defer │ └── main.go ├── 99_others ├── GA │ ├── GA.go │ ├── GA_test.go │ ├── doc.go │ └── readme.md ├── Graph │ ├── Graph.go │ ├── Graph_test.go │ ├── README.MD │ └── test.txt ├── GraphMatrix │ ├── GraphMatrix.go │ ├── GraphMatrix_test.go │ └── test.txt └── ShortestPath │ ├── Dijkstra │ ├── Dijkstra.go │ ├── Dijkstra.txt │ └── Dijkstra_test.go │ ├── Floyd │ ├── Floyd.go │ ├── Floyd.txt │ └── Floyd_test.go │ ├── README.MD │ ├── SPFA │ ├── SPFA.go │ ├── SPFA_test.go │ └── spfa.txt │ └── doc.go ├── README.MD ├── go.mod └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | bin -------------------------------------------------------------------------------- /01_list/00_img/01_链表.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 | 0x1 14 |
15 |
16 |
17 |
18 | 19 | 0x1 20 | 21 |
22 |
23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | root: 0x2 31 |
32 |
33 |
34 |
35 | 36 | root: 0x2 37 | 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 |
47 | len: 1 48 |
49 |
50 |
51 |
52 | 53 | len: 1 54 | 55 |
56 |
57 | 58 | 59 | 60 | 61 | 62 | 63 |
64 |
65 |
66 | list 67 |
68 |
69 |
70 |
71 | 72 | list 73 | 74 |
75 |
76 | 77 | 78 | 79 | 80 | 81 | 82 |
83 |
84 |
85 | prev 86 |
87 |
88 |
89 |
90 | 91 | prev 92 | 93 |
94 |
95 | 96 | 97 | 98 | 99 | 100 | 101 |
102 |
103 |
104 | next 105 |
106 |
107 |
108 |
109 | 110 | next 111 | 112 |
113 |
114 | 115 | 116 | 117 | 118 | 119 | 120 |
121 |
122 |
123 | 0x1 124 |
125 |
126 |
127 |
128 | 129 | 0x1 130 | 131 |
132 |
133 | 134 | 135 | 136 | 137 | 138 | 139 |
140 |
141 |
142 | list 143 |
144 |
145 |
146 |
147 | 148 | list 149 | 150 |
151 |
152 | 153 | 154 | 155 | 156 | 157 | 158 |
159 |
160 |
161 | prev 162 |
163 |
164 |
165 |
166 | 167 | prev 168 | 169 |
170 |
171 | 172 | 173 | 174 | 175 | 176 | 177 |
178 |
179 |
180 | next 181 |
182 |
183 |
184 |
185 | 186 | next 187 | 188 |
189 |
190 | 191 | 192 | 193 | 194 |
195 |
196 |
197 | root: 0x2 198 |
199 |
200 |
201 |
202 | 203 | root: 0x2 204 | 205 |
206 |
207 | 208 | 209 | 210 | 211 |
212 |
213 |
214 | root: 0x3 215 |
216 |
217 |
218 |
219 | 220 | root: 0x3 221 | 222 |
223 |
224 | 225 | 226 | 227 | 228 |
229 |
230 |
231 | len: 0 232 |
233 |
234 |
235 |
236 | 237 | len: 0 238 | 239 |
240 |
241 | 242 | 243 | 244 | 245 |
246 |
247 |
248 | 重置链表前 249 |
250 |
251 |
252 |
253 | 254 | 重置链表前 255 | 256 |
257 |
258 | 259 | 260 | 261 | 262 |
263 |
264 |
265 | 重置链表后 266 |
267 |
268 |
269 |
270 | 271 | 重置链表后 272 | 273 |
274 |
275 | 276 | 277 | 278 | 279 |
280 |
281 |
282 | l 283 |
284 |
285 |
286 |
287 | 288 | l 289 | 290 |
291 |
292 | 293 | 294 | 295 | 296 |
297 |
298 |
299 | l 300 |
301 |
302 |
303 |
304 | 305 | l 306 | 307 |
308 |
309 | 310 | 311 | 312 | 313 |
314 |
315 |
316 | e 317 |
318 |
319 |
320 |
321 | 322 | e 323 | 324 |
325 |
326 | 327 | 328 | 329 | 330 |
331 |
332 |
333 | e 334 |
335 |
336 |
337 |
338 | 339 | e 340 | 341 |
342 |
343 |
344 | 345 | 346 | 347 | 348 | Viewer does not support full SVG 1.1 349 | 350 | 351 | 352 |
-------------------------------------------------------------------------------- /01_list/01_list/list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "container/list" 5 | "sync" 6 | ) 7 | 8 | // List 链表 9 | type List struct { 10 | *list.List 11 | mu sync.Mutex 12 | } 13 | 14 | // New 新建链表 15 | func New() *List { 16 | return &List{List: list.New()} 17 | } 18 | 19 | // PushBack 像链表尾部插入值 20 | func (l *List) PushBack(v interface{}) { 21 | l.mu.Lock() 22 | defer l.mu.Unlock() 23 | l.List.PushBack(v) 24 | } 25 | -------------------------------------------------------------------------------- /01_list/01_list/list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "container/list" 5 | "sync" 6 | "testing" 7 | ) 8 | 9 | // TestList 测试标准库的链表 10 | // go test -race . 11 | func TestList(t *testing.T) { 12 | l := list.New() 13 | wg := sync.WaitGroup{} 14 | wg.Add(1) 15 | go func() { 16 | for i := 0; i < 10; i++ { 17 | l.PushBack(i) 18 | } 19 | wg.Done() 20 | }() 21 | l.PushBack(11) 22 | wg.Wait() 23 | } 24 | 25 | func TestList_PushBack(t *testing.T) { 26 | l := New() 27 | wg := sync.WaitGroup{} 28 | wg.Add(1) 29 | go func() { 30 | for i := 0; i < 10; i++ { 31 | l.PushBack(1) 32 | } 33 | wg.Done() 34 | }() 35 | l.PushBack(11) 36 | wg.Wait() 37 | } 38 | -------------------------------------------------------------------------------- /01_list/02_lru/lru.go: -------------------------------------------------------------------------------- 1 | package lru 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // Node 链表的节点 8 | type Node struct { 9 | prev, next *Node 10 | 11 | list *LRU 12 | 13 | key string 14 | value interface{} 15 | } 16 | 17 | // LRU 缓存 18 | type LRU struct { 19 | root *Node // 根节点 20 | cap int // 当前缓存容量 21 | len int // 缓存的长度 22 | } 23 | 24 | // NewLRU NewLRU 25 | func NewLRU(cap int) *LRU { 26 | l := &LRU{ 27 | root: &Node{}, 28 | cap: cap, 29 | } 30 | l.root.prev = l.root 31 | l.root.next = l.root 32 | l.root.list = l 33 | return l 34 | } 35 | 36 | // Get 获取缓存数据 37 | // 如果获取到数据,就把这个节点移动到链表头部 38 | // 如果没有获取到,就返回nil 39 | func (l *LRU) Get(key string) interface{} { 40 | defer l.debug() 41 | n := l.get(key) 42 | if n == nil { 43 | return nil 44 | } 45 | 46 | return n.value 47 | } 48 | 49 | func (l *LRU) get(key string) *Node { 50 | for n := l.root.next; n != l.root; n = n.next { 51 | if n.key == key { 52 | n.prev.next = n.next 53 | n.next.prev = n.prev 54 | 55 | n.next = l.root.next 56 | l.root.next.prev = n 57 | l.root.next = n 58 | n.prev = l.root 59 | return n 60 | } 61 | } 62 | return nil 63 | } 64 | 65 | // Put 写入缓存数据 66 | // 如果 key 已经存在,那么更新值 67 | // 如果 key 不存在,那么插入到第一个节点 68 | // 当缓存容量满了的时候,会自动删除最后的数据 69 | func (l *LRU) Put(key string, value interface{}) { 70 | defer l.debug() 71 | n := l.get(key) 72 | if n != nil { 73 | n.value = value 74 | return 75 | } 76 | 77 | // 缓存满了 78 | if l.len == l.cap { 79 | last := l.root.prev 80 | last.prev.next = l.root 81 | l.root.prev = last.prev 82 | last.list = nil 83 | last.prev = nil 84 | last.next = nil 85 | l.len-- 86 | } 87 | 88 | node := &Node{key: key, value: value} 89 | head := l.root.next 90 | head.prev = node 91 | node.next = head 92 | node.prev = l.root 93 | l.root.next = node 94 | l.len++ 95 | node.list = l 96 | } 97 | 98 | // debug for debug 99 | func (l *LRU) debug() { 100 | fmt.Println("lru len: ", l.len) 101 | fmt.Println("lru cap: ", l.cap) 102 | for n := l.root.next; n != l.root; n = n.next { 103 | fmt.Printf("%s:%v -> ", n.key, n.value) 104 | } 105 | fmt.Println() 106 | fmt.Println() 107 | } 108 | -------------------------------------------------------------------------------- /01_list/02_lru/lru_test.go: -------------------------------------------------------------------------------- 1 | package lru 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestNewLRU(t *testing.T) { 10 | l := NewLRU(3) 11 | assert.Equal(t, l.Get(""), nil) 12 | 13 | l.Put("1", 1) 14 | l.Put("2", 2) 15 | l.Put("3", 3) 16 | assert.Equal(t, 3, l.Get("3")) 17 | assert.Equal(t, 1, l.Get("1")) 18 | 19 | l.Put("4", 4) 20 | assert.Equal(t, nil, l.Get("2")) 21 | 22 | l.Put("3", 31) 23 | assert.Equal(t, 31, l.Get("3")) 24 | } 25 | -------------------------------------------------------------------------------- /01_list/03_q1_list_bug/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "container/list" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | l := list.List{} 10 | e := l.PushBack(10) 11 | 12 | l = list.List{} 13 | l.Remove(e) 14 | fmt.Println("list len: ", l.Len()) 15 | } 16 | -------------------------------------------------------------------------------- /02_array/00_img/01_array.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | a[0] 12 |
13 |
14 |
15 |
16 | 17 | a[0] 18 | 19 |
20 |
21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | 29 | a[1] 30 | 31 |
32 |
33 |
34 |
35 | 36 | a[1] 37 | 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 |
47 | 48 | a[2] 49 | 50 |
51 |
52 |
53 |
54 | 55 | a[2] 56 | 57 |
58 |
59 | 60 | 61 | 62 | 63 |
64 |
65 |
66 | 67 | a[3] 68 | 69 |
70 |
71 |
72 |
73 | 74 | a[3] 75 | 76 |
77 |
78 | 79 | 80 | 81 | 82 |
83 |
84 |
85 | 86 | a[4] 87 | 88 |
89 |
90 |
91 |
92 | 93 | a[4] 94 | 95 |
96 |
97 | 98 | 99 | 100 | 101 |
102 |
103 |
104 | 0x1 105 |
106 |
107 |
108 |
109 | 110 | 0x1 111 | 112 |
113 |
114 | 115 | 116 | 117 | 118 |
119 |
120 |
121 | 0x2 122 |
123 |
124 |
125 |
126 | 127 | 0x2 128 | 129 |
130 |
131 | 132 | 133 | 134 | 135 |
136 |
137 |
138 | 0x3 139 |
140 |
141 |
142 |
143 | 144 | 0x3 145 | 146 |
147 |
148 | 149 | 150 | 151 | 152 |
153 |
154 |
155 | 0x4 156 |
157 |
158 |
159 |
160 | 161 | 0x4 162 | 163 |
164 |
165 | 166 | 167 | 168 | 169 |
170 |
171 |
172 | 0x5 173 |
174 |
175 |
176 |
177 | 178 | 0x5 179 | 180 |
181 |
182 | 183 | 184 | 185 | 186 | 187 |
188 |
189 |
190 | 数组: a 191 |
192 |
193 |
194 |
195 | 196 | 数组: a 197 | 198 |
199 |
200 |
201 | 202 | 203 | 204 | 205 | Viewer does not support full SVG 1.1 206 | 207 | 208 | 209 |
-------------------------------------------------------------------------------- /02_array/00_img/02_slice_struct.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | len(int) 12 |
13 |
14 |
15 |
16 | 17 | len(int) 18 | 19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | array(pointer) 31 |
32 |
33 |
34 |
35 | 36 | array(pointer) 37 | 38 |
39 |
40 | 41 | 42 | 43 | 44 |
45 |
46 |
47 | cap(int) 48 |
49 |
50 |
51 |
52 | 53 | cap(int) 54 | 55 |
56 |
57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 |
66 |
67 |
68 | Array 69 |
70 |
71 |
72 |
73 | 74 | Array 75 | 76 |
77 |
78 | 79 | 80 | 81 | 82 |
83 |
84 |
85 | slice 86 |
87 |
88 |
89 |
90 | 91 | slice 92 | 93 |
94 |
95 |
96 | 97 | 98 | 99 | 100 | Viewer does not support full SVG 1.1 101 | 102 | 103 | 104 |
-------------------------------------------------------------------------------- /02_array/01_array_example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | ) 7 | 8 | func main() { 9 | // 初始化数组 10 | var arr = [3]int{1, 2, 3} 11 | // 查找元素 12 | fmt.Printf("arr[1]: %d\n", arr[1]) 13 | // 删除元素 14 | remove(&arr, 2) 15 | // remove(&arr, 3) // will panic 16 | fmt.Println(arr) 17 | 18 | fmt.Printf("main: %p --> %+v\n", &arr, arr) 19 | p(arr) 20 | p2(&arr) 21 | } 22 | 23 | // 删除数组 arr 的某个元素 24 | // index 为需要删除的索引 25 | // 从需要删除的元素开始,依次将后面的元素往前移动一位即可 26 | // 然后将最后一位修改为该类型的默认值 27 | func remove(arr *[3]int, index int) { 28 | if index >= len(arr) { 29 | log.Panicf("%d remove out range arr", index) 30 | } 31 | for i := index; i < len(arr)-1; i++ { 32 | arr[i] = arr[i+1] 33 | } 34 | arr[len(arr)-1] = 0 35 | } 36 | 37 | func p(arr [3]int) { 38 | fmt.Printf("p: %p --> %+v\n", &arr, arr) 39 | } 40 | 41 | func p2(arr *[3]int) { 42 | fmt.Printf("p2: %p --> %+v\n", arr, arr) 43 | } 44 | -------------------------------------------------------------------------------- /02_array/02_slice/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // 初始化 7 | s1 := make([]int, 2) 8 | fmt.Printf("s1(%p): %v, len: %d, cap: %d\n", &s1, s1, len(s1), cap(s1)) 9 | // s1(0xc00000c080): [0 0], len: 2, cap: 2 10 | 11 | // 赋值 12 | s1[0] = 1 13 | s1[1] = 2 14 | fmt.Printf("s1(%p): %v, len: %d, cap: %d\n", &s1, s1, len(s1), cap(s1)) 15 | // s1(0xc00000c080): [1 2], len: 2, cap: 2 16 | 17 | // 扩容 18 | s1 = append(s1, 3, 4, 5, 6, 7) 19 | fmt.Printf("s1(%p): %v, len: %d, cap: %d\n", &s1, s1, len(s1), cap(s1)) 20 | // s1(0xc00000c080): [1 2 3], len: 3, cap: 4 21 | 22 | // 删除元素 23 | s1 = append(s1[:1], s1[2:]...) 24 | fmt.Printf("s1(%p): %v, len: %d, cap: %d\n", &s1, s1, len(s1), cap(s1)) 25 | // s1(0xc00000c080): [1 3], len: 2, cap: 4 26 | 27 | // 复制一个 slice 28 | s2 := s1[:2] 29 | fmt.Printf("s2(%p): %v, len: %d, cap: %d\n", &s2, s2, len(s2), cap(s2)) 30 | // s2(0xc00000c120): [1 3], len: 2, cap: 4 31 | 32 | s1[0] = 10 // 这里可以发现,s1[0] s2[0] 都被修改为了 10 33 | fmt.Printf("s1(%p): %v, len: %d, cap: %d\n", &s1, s1, len(s1), cap(s1)) 34 | // s1(0xc00000c080): [10 3], len: 2, cap: 4 35 | fmt.Printf("s2(%p): %v, len: %d, cap: %d\n", &s2, s2, len(s2), cap(s2)) 36 | // s2(0xc00000c120): [10 3], len: 2, cap: 4 37 | 38 | s1 = append(s1, 5, 6, 7, 8) 39 | s1[0] = 11 // 这里可以发现,s1[0] 被修改为了 11, s2[0] 还是10 40 | fmt.Printf("s1(%p): %v, len: %d, cap: %d\n", &s1, s1, len(s1), cap(s1)) 41 | // s1(0xc00011c020): [11 3 5 6 7 8], len: 6, cap: 8 42 | fmt.Printf("s2(%p): %v, len: %d, cap: %d\n", &s2, s2, len(s2), cap(s2)) 43 | // s2(0xc00011c0c0): [10 3], len: 2, cap: 4 44 | 45 | // 对比一下两种空 slice 的区别 46 | var s3 []int 47 | s4 := make([]int, 0) 48 | fmt.Printf("%p --> %#v\n", s3, s3) // 0x0 --> []int(nil) 49 | fmt.Printf("%p --> %#v\n", s4, s4) // 0x587450 --> []int{} 50 | 51 | initSlice() 52 | } 53 | 54 | func sliceChange(s []int) { 55 | // 不允许直接这么操作 56 | s[0] = 1 57 | } 58 | 59 | func initSlice() { 60 | var s1 []int 61 | fmt.Printf("%p: %v, len: %d, cap: %d\n", s1, s1, len(s1), cap(s1)) 62 | s2 := make([]uint, 0) 63 | fmt.Printf("%p: %v, len: %d, cap: %d\n", s2, s2, len(s2), cap(s2)) 64 | s3 := []int{} 65 | fmt.Printf("%p: %v, len: %d, cap: %d\n", s3, s3, len(s3), cap(s3)) 66 | } 67 | -------------------------------------------------------------------------------- /02_array/03_q1_slice_cap/main.go: -------------------------------------------------------------------------------- 1 | // Package main What will eventually be output? 2 | // A: 5 8 B: 8 8 C: 5 5 D: 5 6 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func main() { 10 | s := []int{1, 2} 11 | s = append(s, 3, 4, 5) 12 | fmt.Println(len(s), cap(s)) 13 | } 14 | -------------------------------------------------------------------------------- /03_stack/00_img/01_stack.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 | 1 15 |
16 |
17 |
18 |
19 | 20 | 1 21 | 22 |
23 |
24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | 2 32 |
33 |
34 |
35 |
36 | 37 | 2 38 | 39 |
40 |
41 | 42 | 43 | 44 | 45 |
46 |
47 |
48 | 3 49 |
50 |
51 |
52 |
53 | 54 | 3 55 | 56 |
57 |
58 | 59 | 60 | 61 | 62 |
63 |
64 |
65 | 4 66 |
67 |
68 |
69 |
70 | 71 | 4 72 | 73 |
74 |
75 | 76 | 77 | 78 | 79 |
80 |
81 |
82 | 5 83 |
84 |
85 |
86 |
87 | 88 | 5 89 | 90 |
91 |
92 | 93 | 94 | 95 | 96 |
97 |
98 |
99 | 6 100 |
101 |
102 |
103 |
104 | 105 | 6 106 | 107 |
108 |
109 | 110 | 111 | 112 | 113 |
114 | 115 | 116 | 117 | 118 | Viewer does not support full SVG 1.1 119 | 120 | 121 | 122 |
-------------------------------------------------------------------------------- /03_stack/01_array_stack/stack.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | // Stack Stack 4 | type Stack struct { 5 | items []string 6 | current int 7 | } 8 | 9 | // NewStack NewStack 10 | func NewStack() *Stack { 11 | return &Stack{ 12 | items: make([]string, 10), 13 | current: 0, 14 | } 15 | } 16 | 17 | // Push 入栈 18 | func (s *Stack) Push(item string) { 19 | s.current++ 20 | // 判断底层 slice 是否满了,如果满了就 append 21 | if s.current == len(s.items) { 22 | s.items = append(s.items, item) 23 | return 24 | } 25 | s.items[s.current] = item 26 | } 27 | 28 | // Pop 出栈 29 | func (s *Stack) Pop() string { 30 | if s.current == 0 { 31 | return "" 32 | } 33 | item := s.items[s.current] 34 | s.current-- 35 | return item 36 | } 37 | -------------------------------------------------------------------------------- /03_stack/01_array_stack/stack_test.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestNewStack(t *testing.T) { 11 | stack := NewStack() 12 | assert.Equal(t, "", stack.Pop()) 13 | stack.Push("1") 14 | stack.Push("2") 15 | assert.Equal(t, "2", stack.Pop()) 16 | assert.Equal(t, "1", stack.Pop()) 17 | for i := 3; i < 20; i++ { 18 | stack.Push(strconv.Itoa(i)) 19 | } 20 | assert.Equal(t, "19", stack.Pop()) 21 | } 22 | -------------------------------------------------------------------------------- /03_stack/02_list_stack/stack.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | // node 节点 4 | type node struct { 5 | prev, next *node 6 | value string 7 | } 8 | 9 | // Stack 链式栈 10 | type Stack struct { 11 | root *node 12 | len int 13 | } 14 | 15 | // NewStack NewStack 16 | func NewStack() *Stack { 17 | n := &node{} 18 | n.next = n 19 | n.prev = n 20 | return &Stack{root: n} 21 | } 22 | 23 | // Push 入栈 24 | func (s *Stack) Push(item string) { 25 | n := &node{value: item} 26 | s.root.prev.next = n 27 | n.prev = s.root.prev 28 | n.next = s.root 29 | s.root.prev = n 30 | s.len++ 31 | } 32 | 33 | // Pop 出栈 34 | func (s *Stack) Pop() string { 35 | item := s.root.prev 36 | if item == s.root { 37 | return "" 38 | } 39 | 40 | s.root.prev = item.prev 41 | item.prev.next = s.root 42 | // 避免内存泄漏 43 | item.prev = nil 44 | item.next = nil 45 | s.len-- 46 | return item.value 47 | } 48 | -------------------------------------------------------------------------------- /03_stack/02_list_stack/stack_test.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestNewStack(t *testing.T) { 11 | stack := NewStack() 12 | assert.Equal(t, "", stack.Pop()) 13 | stack.Push("1") 14 | stack.Push("2") 15 | assert.Equal(t, "2", stack.Pop()) 16 | assert.Equal(t, "1", stack.Pop()) 17 | for i := 3; i < 20; i++ { 18 | stack.Push(strconv.Itoa(i)) 19 | } 20 | assert.Equal(t, "19", stack.Pop()) 21 | } 22 | -------------------------------------------------------------------------------- /03_stack/03_calculation/calculation.go: -------------------------------------------------------------------------------- 1 | package calculation 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | // 操作符的优先级 9 | var operatorPriority = map[string]int{ 10 | "+": 0, 11 | "-": 0, 12 | "*": 1, 13 | "/": 1, 14 | "(": 2, 15 | ")": 2, 16 | } 17 | 18 | // Calculator 计算器 19 | type Calculator struct { 20 | nums *StackInt 21 | operators *Stack 22 | exp string 23 | } 24 | 25 | // NewCalculator NewCalculator 26 | func NewCalculator(exp string) *Calculator { 27 | return &Calculator{ 28 | nums: NewStackInt(), 29 | operators: NewStack(), 30 | exp: exp, 31 | } 32 | } 33 | 34 | // Calculate 获取计算结果 35 | func (c *Calculator) Calculate() int { 36 | l := len(c.exp) 37 | for i := 0; i < l; i++ { 38 | switch e := (c.exp[i]); e { 39 | case ' ': 40 | continue 41 | case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 42 | // 一直往后获取数字,如果下一个还是数字说明这一个数还不完整 43 | j := i 44 | for j < l && c.exp[j] <= '9' && c.exp[j] >= '0' { 45 | j++ 46 | } 47 | n, _ := strconv.Atoi(c.exp[i:j]) 48 | i = j - 1 49 | c.nums.Push(n) 50 | case '+', '-', '*', '/': 51 | // 从计算符栈中获取栈顶元素,如果当前操作符的优先级低于栈顶元素的优先级 52 | // 并且栈顶元素不为空,和括号 53 | // 那么从数据栈中取两个数据和栈顶操作符进行计算 54 | pre := c.operators.Pop() 55 | for pre != "" && pre != "(" && operatorPriority[string(e)] <= operatorPriority[pre] { 56 | c.nums.Push(c.calc(pre)) 57 | pre = c.operators.Pop() 58 | } 59 | if pre != "" { 60 | c.operators.Push(pre) 61 | } 62 | c.operators.Push(string(e)) 63 | case '(': 64 | c.operators.Push(string(e)) 65 | case ')': 66 | // 碰到右括号之后就一直不断操作符栈中弹出元素,并且取两个数据进行计算 67 | // 直到碰到左括号为止 68 | for o := c.operators.Pop(); o != "(" && o != ""; o = c.operators.Pop() { 69 | c.nums.Push(c.calc(o)) 70 | } 71 | default: 72 | panic("invalid exp") 73 | } 74 | } 75 | // 最后如果不存在操作符,说明数据栈中的栈顶元素就是最后结果 76 | o := c.operators.Pop() 77 | if o == "" { 78 | return c.nums.Pop() 79 | } 80 | // 如果存在,就把最后的数据进行计算后返回 81 | return c.calc(o) 82 | } 83 | 84 | // calc 单次计算操作,o: 计算符 85 | func (c *Calculator) calc(o string) int { 86 | b := c.nums.Pop() 87 | a := c.nums.Pop() 88 | 89 | fmt.Printf("%d %s %d\n", a, o, b) 90 | 91 | switch o { 92 | case "+": 93 | return a + b 94 | case "-": 95 | return a - b 96 | case "*": 97 | return a * b 98 | case "/": 99 | return a / b 100 | } 101 | 102 | return 0 103 | } 104 | 105 | // calculate 计算器,支持加减乘除 106 | func calculate(s string) int { 107 | return NewCalculator(s).Calculate() 108 | } 109 | -------------------------------------------------------------------------------- /03_stack/03_calculation/calculation_test.go: -------------------------------------------------------------------------------- 1 | package calculation 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func Test_calculate(t *testing.T) { 11 | tests := []struct { 12 | exp string 13 | want int 14 | }{ 15 | { 16 | exp: " 2-1 + 2 ", 17 | want: 3, 18 | }, 19 | { 20 | exp: "(1+(4+5+2)-3)+(6+8)", 21 | want: 23, 22 | }, 23 | { 24 | exp: "(1+(4+5+2)-3)*(6+8)", 25 | want: 126, 26 | }, 27 | { 28 | exp: "1-11", 29 | want: -10, 30 | }, 31 | } 32 | for _, tt := range tests { 33 | t.Run(fmt.Sprintf("%s = %d", tt.exp, tt.want), func(t *testing.T) { 34 | assert.Equal(t, tt.want, calculate(tt.exp)) 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /03_stack/03_calculation/stack_int.go: -------------------------------------------------------------------------------- 1 | package calculation 2 | 3 | // StackInt StackInt 4 | type StackInt struct { 5 | items []int 6 | current int 7 | } 8 | 9 | // NewStackInt NewStackInt 10 | func NewStackInt() *StackInt { 11 | return &StackInt{ 12 | items: make([]int, 10), 13 | current: 0, 14 | } 15 | } 16 | 17 | // Push 入栈 18 | func (s *StackInt) Push(item int) { 19 | s.current++ 20 | // 判断底层 slice 是否满了,如果满了就 append 21 | if s.current == len(s.items) { 22 | s.items = append(s.items, item) 23 | return 24 | } 25 | s.items[s.current] = item 26 | } 27 | 28 | // Pop 出栈 29 | func (s *StackInt) Pop() int { 30 | if s.current == 0 { 31 | return 0 32 | } 33 | item := s.items[s.current] 34 | s.current-- 35 | return item 36 | } 37 | -------------------------------------------------------------------------------- /03_stack/03_calculation/stack_string.go: -------------------------------------------------------------------------------- 1 | package calculation 2 | 3 | // Stack Stack 4 | type Stack struct { 5 | items []string 6 | current int 7 | } 8 | 9 | // NewStack NewStack 10 | func NewStack() *Stack { 11 | return &Stack{ 12 | items: make([]string, 10), 13 | current: 0, 14 | } 15 | } 16 | 17 | // Push 入栈 18 | func (s *Stack) Push(item string) { 19 | s.current++ 20 | // 判断底层 slice 是否满了,如果满了就 append 21 | if s.current == len(s.items) { 22 | s.items = append(s.items, item) 23 | return 24 | } 25 | s.items[s.current] = item 26 | } 27 | 28 | // Pop 出栈 29 | func (s *Stack) Pop() string { 30 | if s.current == 0 { 31 | return "" 32 | } 33 | item := s.items[s.current] 34 | s.current-- 35 | return item 36 | } 37 | -------------------------------------------------------------------------------- /03_stack/04_defer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | f0() 7 | f1() 8 | f2() 9 | 10 | fmt.Println("f3:", f3()) 11 | fmt.Println("f4:", f4()) 12 | 13 | f5() 14 | } 15 | 16 | // 基本用法:延迟调用,清理资源 17 | func f0() { 18 | defer fmt.Println("clean") 19 | fmt.Println("hello") 20 | } 21 | 22 | // 基本用法1: 后进先出 23 | func f1() { 24 | defer fmt.Println("1") 25 | defer fmt.Println("2") 26 | 27 | fmt.Println("3") 28 | } 29 | 30 | // 基本用法2:异常恢复 31 | func f2() { 32 | defer func() { 33 | if err := recover(); err != nil { 34 | fmt.Printf("paniced: %+v", err) 35 | } 36 | }() 37 | panic("test") 38 | } 39 | 40 | // 容易掉坑1:函数变量修改 41 | func f3() (res int) { 42 | defer func() { 43 | res++ 44 | }() 45 | return 0 46 | } 47 | 48 | // 容易掉坑之2:参数复制 49 | func f4() (res int) { 50 | defer func(res int) { 51 | res++ 52 | }(res) 53 | return 0 54 | } 55 | 56 | // 容易掉坑3:值 57 | func f5() { 58 | i := 0 59 | defer fmt.Println(i) 60 | i++ 61 | return 62 | } 63 | 64 | // 循环defer不可取 65 | func f6() { 66 | for i := 0; i < 10; i++ { 67 | defer func() { 68 | fmt.Printf("f6: %d\n", i) 69 | }() 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /99_others/GA/GA.go: -------------------------------------------------------------------------------- 1 | package GA 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "math/rand" 7 | "time" 8 | ) 9 | 10 | var ( 11 | groupSize int //种群大小 12 | chromosomeSize int //染色体长度 13 | selectRand float64 //轮盘选择概率 14 | crossRand float64 //交叉概率 15 | mutationRand float64 //变异概率 16 | group []Person //种群 17 | bestPerson Person //当前最好的个体 18 | r *rand.Rand 19 | ) 20 | 21 | //Person 个体 22 | type Person struct { 23 | chromosome []int //染色体 24 | value float64 //适应值 25 | } 26 | 27 | //Init 初始化函数 28 | //初始化设置种群大小、轮盘选择概率、交叉概率已经变异的概率 29 | func Init(GroupSize, ChromosomeSize int, SelectRand, CrossRand, MutationRand float64) { 30 | groupSize = GroupSize 31 | crossRand = CrossRand 32 | selectRand = SelectRand 33 | mutationRand = MutationRand 34 | chromosomeSize = ChromosomeSize 35 | r = rand.New(rand.NewSource(time.Now().UnixNano())) 36 | bestPerson.chromosome = make([]int, chromosomeSize) 37 | } 38 | 39 | //InitGroup 初始化种群 40 | //根据种群大小随机产生一些个体填充 41 | func InitGroup() { 42 | group = make([]Person, groupSize) 43 | for i := 0; i < groupSize; i++ { 44 | group[i].chromosome = make([]int, chromosomeSize) 45 | for j := 0; j < chromosomeSize; j++ { 46 | if r.Float64() > selectRand { 47 | group[i].chromosome[j] = 1 48 | } 49 | } 50 | } 51 | } 52 | 53 | //Fitness 计算适应值 54 | func Fitness(person Person) float64 { 55 | x := decode(person) 56 | return x + 10*math.Sin(5*x) + 7*math.Cos(4*x) 57 | } 58 | 59 | //解码 60 | func decode(person Person) float64 { 61 | var sum float64 62 | //解码 63 | for i := 0; i < chromosomeSize; i++ { 64 | //二进制染色体转十进制值 65 | if person.chromosome[i] == 1 { 66 | sum = sum + math.Pow(2.0, float64(i)) 67 | } 68 | } 69 | return sum * 9 / (math.Pow(2.0, 14.0) - 1) 70 | } 71 | 72 | //Select 选择 73 | func Select() { 74 | newGroup := make([]Person, groupSize) 75 | for i := 0; i < groupSize; i++ { 76 | newGroup[i].chromosome = make([]int, chromosomeSize) 77 | rnd := r.Float64() 78 | 79 | A: 80 | for j := 0; j < groupSize; j++ { 81 | if group[j].value > rnd*bestPerson.value { 82 | copy(newGroup[i].chromosome, group[j].chromosome) 83 | break A 84 | } 85 | if j == groupSize-1 { 86 | copy(newGroup[i].chromosome, bestPerson.chromosome) 87 | } 88 | } 89 | } 90 | group = newGroup 91 | newGroup = nil 92 | } 93 | 94 | //Cross 交叉 95 | func Cross() { 96 | for i := 0; i < groupSize; i = i + 2 { 97 | if r.Float64() < crossRand { 98 | crossPosition := r.Intn(chromosomeSize - 1) 99 | if crossPosition == 0 || crossPosition == 1 { 100 | continue 101 | } 102 | //交叉 103 | for j := crossPosition; j < chromosomeSize; j++ { 104 | tmp := group[i].chromosome[j] 105 | group[i].chromosome[j] = group[i+1].chromosome[j] 106 | group[i+1].chromosome[j] = tmp 107 | } 108 | } 109 | } 110 | } 111 | 112 | //Mutation 变异 113 | func Mutation() { 114 | for i := 0; i < groupSize; i++ { 115 | if r.Float64() < mutationRand { 116 | mutationPosition := r.Intn(chromosomeSize - 1) 117 | 118 | //单点变异 119 | if group[i].chromosome[mutationPosition] == 0 { 120 | group[i].chromosome[mutationPosition] = 1 121 | } else { 122 | group[i].chromosome[mutationPosition] = 0 123 | } 124 | } 125 | } 126 | } 127 | 128 | //GA 遗传算法 129 | func GA() { 130 | //初始化 131 | Init(100, 14, 0.5, 0.6, 0.05) 132 | //初始化种群 133 | InitGroup() 134 | 135 | //遗传循环 136 | for i := 0; i < 1000; i++ { 137 | 138 | //计算适应值 139 | for j := 0; j < groupSize; j++ { 140 | group[j].value = Fitness(group[j]) 141 | 142 | //保存当前最好的个体 143 | if group[j].value > bestPerson.value { 144 | copy(bestPerson.chromosome, group[j].chromosome) 145 | bestPerson.value = group[j].value 146 | } 147 | } 148 | 149 | fmt.Println("第", i, "代最好个体:", bestPerson.value, " ", decode(bestPerson)) 150 | 151 | //选择 152 | Select() 153 | 154 | //交叉 155 | Cross() 156 | 157 | //变异 158 | Mutation() 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /99_others/GA/GA_test.go: -------------------------------------------------------------------------------- 1 | package GA 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test(t *testing.T) { 8 | GA() 9 | } 10 | -------------------------------------------------------------------------------- /99_others/GA/doc.go: -------------------------------------------------------------------------------- 1 | //Package GA 遗传算法的Golang实现 2 | //遗传算法的计算流程 编码->获得初始群体->计算适应值->产生新的群体(选择、交叉、变异等)->满足要求->解码->获得近似解 3 | //例子:求解函数 f(x) = x + 10*sin(5*x) + 7*cos(4*x) 在区间[0,9]的最大值。 4 | //假设求解精度为3,那么需要求解的值可能为 0.000-9.000 可能性在2^13-2^14这个范围之内 5 | //使用一个14为的二进制字符串即可表示,最终的求解域 6 | //解码 f(x), x∈[lower_bound, upper_bound] x = lower_bound + decimal(chromosome)×(upper_bound-lower_bound)/( 2 ^chromosome_size- 1 ) 7 | package GA 8 | -------------------------------------------------------------------------------- /99_others/GA/readme.md: -------------------------------------------------------------------------------- 1 | # 遗传算法 2 | 3 | -------------------------------------------------------------------------------- /99_others/Graph/Graph.go: -------------------------------------------------------------------------------- 1 | //Package Graph 邻接表 2 | package Graph 3 | 4 | import ( 5 | "bufio" 6 | "io" 7 | "os" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | // EdgeType 边的权值类型 13 | type EdgeType int 14 | 15 | // VextexType 顶点类型定义 16 | type VextexType int 17 | 18 | // VextexDataType 顶点值类型定义 19 | type VextexDataType int 20 | 21 | //EdgeNode 边的节点 22 | type EdgeNode struct { 23 | Weight EdgeType //权值 24 | V VextexType //指向储存该顶点的下标 25 | Next *EdgeNode //指向下一条边 26 | } 27 | 28 | //VextexNode 顶点节点定义 29 | type VextexNode struct { 30 | data VextexDataType //顶点的值 31 | FisrtEdge *EdgeNode //该顶点指向的第一条边 32 | } 33 | 34 | //Graph 图 35 | type Graph struct { 36 | VNum, ENum int //顶点数目,边数目 37 | G []VextexNode //邻接表 38 | } 39 | 40 | //CreateGraph 创建邻接表 41 | func CreateGraph(VNum int) (graph Graph) { 42 | graph.VNum = VNum 43 | graph.G = make([]VextexNode, VNum) 44 | for i := 0; i < VNum; i++ { 45 | graph.G[i] = VextexNode{} 46 | } 47 | return graph 48 | } 49 | 50 | //AddEdge 添加边 51 | func (graph Graph) AddEdge(s, t VextexType, weight EdgeType) { 52 | edge := &EdgeNode{V: t, Weight: weight} 53 | 54 | //添加边到头部 55 | edge.Next = graph.G[s].FisrtEdge 56 | graph.G[s].FisrtEdge = edge 57 | } 58 | 59 | //BuildGraph 通过读取文件建图 60 | //文件格式要求: 61 | //顶点个数 边数 62 | //顶点v1 顶点V2 边的权重 63 | //... 64 | func BuildGraph(path string) (graph Graph) { 65 | f, err := os.Open(path) 66 | if err != nil { 67 | panic(err) 68 | } 69 | buf := bufio.NewReader(f) 70 | 71 | i := 0 72 | //边的数目 73 | for { 74 | line, err := buf.ReadString('\n') 75 | if err != nil { 76 | if err == io.EOF { 77 | return graph 78 | } 79 | panic(err) 80 | } 81 | line = strings.TrimSpace(line) 82 | data := strings.Split(line, " ") 83 | if i == 0 { 84 | n, err := strconv.Atoi(data[0]) 85 | if err != nil { 86 | panic(err) 87 | } 88 | graph = CreateGraph(n) 89 | 90 | graph.ENum, err = strconv.Atoi(data[1]) 91 | if err != nil { 92 | panic(err) 93 | } 94 | } else if i <= graph.ENum { 95 | s, err := strconv.Atoi(data[0]) 96 | if err != nil { 97 | panic(err) 98 | } 99 | t, err := strconv.Atoi(data[1]) 100 | if err != nil { 101 | panic(err) 102 | } 103 | weight, err := strconv.Atoi(data[2]) 104 | if err != nil { 105 | panic(err) 106 | } 107 | graph.AddEdge(VextexType(s), VextexType(t), EdgeType(weight)) 108 | } 109 | i++ 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /99_others/Graph/Graph_test.go: -------------------------------------------------------------------------------- 1 | package Graph 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGraph(t *testing.T) { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /99_others/Graph/README.MD: -------------------------------------------------------------------------------- 1 | Graph 2 | ==== 3 | 4 | 邻接表法建图 -------------------------------------------------------------------------------- /99_others/Graph/test.txt: -------------------------------------------------------------------------------- 1 | 3 3 2 | 0 1 1 3 | 0 2 2 4 | 1 2 3 5 | -------------------------------------------------------------------------------- /99_others/GraphMatrix/GraphMatrix.go: -------------------------------------------------------------------------------- 1 | //Package GraphMatrix 邻接矩阵表示图 2 | package GraphMatrix 3 | 4 | import ( 5 | "bufio" 6 | "io" 7 | "os" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | // EdgeType 边的权值类型 13 | type EdgeType int 14 | 15 | //INF 无穷大 16 | const INF = 0xfffff 17 | 18 | //Graph 图 19 | type Graph struct { 20 | VNum, ENum int //顶点、边的个数 21 | G [][]EdgeType //邻接矩阵 22 | } 23 | 24 | //CreateGraph 创建一个图并且初始化邻接矩阵 25 | func CreateGraph(n int) (graph Graph) { 26 | graph = Graph{VNum: n} 27 | graph.G = make([][]EdgeType, n) 28 | for i := 0; i < n; i++ { 29 | graph.G[i] = make([]EdgeType, n) 30 | for j := 0; j < n; j++ { 31 | graph.G[i][j] = INF 32 | if i == j { 33 | graph.G[i][j] = 0 34 | } 35 | } 36 | } 37 | return graph 38 | } 39 | 40 | //BuildGraph 创建图 41 | func BuildGraph(path string) (graph Graph) { 42 | f, err := os.Open(path) 43 | if err != nil { 44 | panic(err) 45 | } 46 | buf := bufio.NewReader(f) 47 | 48 | i := 0 49 | //边的数目 50 | for { 51 | line, err := buf.ReadString('\n') 52 | if err != nil { 53 | if err == io.EOF { 54 | return graph 55 | } 56 | panic(err) 57 | } 58 | line = strings.TrimSpace(line) 59 | data := strings.Split(line, " ") 60 | if i == 0 { 61 | n, err := strconv.Atoi(data[0]) 62 | if err != nil { 63 | panic(err) 64 | } 65 | graph = CreateGraph(n) 66 | 67 | graph.ENum, err = strconv.Atoi(data[1]) 68 | if err != nil { 69 | panic(err) 70 | } 71 | } else if i <= graph.ENum { 72 | s, err := strconv.Atoi(data[0]) 73 | if err != nil { 74 | panic(err) 75 | } 76 | t, err := strconv.Atoi(data[1]) 77 | if err != nil { 78 | panic(err) 79 | } 80 | weight, err := strconv.Atoi(data[2]) 81 | if err != nil { 82 | panic(err) 83 | } 84 | 85 | //有向图,如果是无向图再添加一条反向边 86 | graph.G[s][t] = EdgeType(weight) 87 | } 88 | i++ 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /99_others/GraphMatrix/GraphMatrix_test.go: -------------------------------------------------------------------------------- 1 | package GraphMatrix 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestGraph(t *testing.T) { 9 | graph := BuildGraph("test.txt") 10 | fmt.Println(graph) 11 | } 12 | -------------------------------------------------------------------------------- /99_others/GraphMatrix/test.txt: -------------------------------------------------------------------------------- 1 | 3 3 2 | 0 1 1 3 | 0 2 2 4 | 1 2 3 5 | -------------------------------------------------------------------------------- /99_others/ShortestPath/Dijkstra/Dijkstra.go: -------------------------------------------------------------------------------- 1 | package Diijkstra 2 | 3 | import ( 4 | "errors" 5 | 6 | "container/list" 7 | 8 | "github.com/mohuishou/algorithm/Graph" 9 | ) 10 | 11 | //INF 无穷大 12 | const INF = 0xffffff 13 | 14 | //Dijkstra 算法 15 | //一种求单源最短路径的算法 16 | func Dijkstra(graph Graph.Graph, s Graph.VextexType, dist []Graph.EdgeType, path []Graph.VextexType) { 17 | //标记顶点是否曾经入队 18 | visited := make([]bool, graph.VNum) 19 | //初始化 20 | for i := 0; i < graph.VNum; i++ { 21 | dist[i] = INF //距离为无穷大 22 | path[i] = -1 //没有上一个节点 23 | visited[i] = false 24 | } 25 | path[s] = s 26 | dist[s] = 0 27 | 28 | //使用list实现一个队列操作 29 | q := list.New() 30 | 31 | //将点s入队 32 | q.PushBack(s) 33 | for q.Len() != 0 { 34 | u := q.Front().Value.(Graph.VextexType) 35 | q.Remove(q.Front()) 36 | //如果该点周围的点已经走过,则无需再走 37 | if visited[u] { 38 | continue 39 | } 40 | 41 | //将该点加入已观察 42 | visited[u] = true 43 | 44 | e := graph.G[u].FisrtEdge 45 | 46 | for e != nil { 47 | //这条边下的顶点 48 | v := e.V 49 | 50 | //如果该点尚未走过,并且当前点的距离加上边的距离小于之前该点的距离,那么就更新该点的距离 51 | if visited[v] == false && dist[v] > dist[u]+e.Weight { 52 | dist[v] = dist[u] + e.Weight //更新该点距离 53 | path[v] = u //更新父节点 54 | q.PushBack(v) //将该点入队 55 | } 56 | e = e.Next 57 | } 58 | 59 | } 60 | 61 | } 62 | 63 | //GetPathForDijkstra 通过路径获得到指定目的节点的路径 64 | func GetPathForDijkstra(path []Graph.VextexType, t Graph.VextexType) ([]Graph.VextexType, error) { 65 | tPath := make([]Graph.VextexType, 0) 66 | for { 67 | tPath = append(tPath, t) 68 | if path[t] == -1 { 69 | return nil, errors.New("不存在到该节点的路径") 70 | } 71 | if t == path[t] { 72 | return tPath, nil 73 | } 74 | t = path[t] 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /99_others/ShortestPath/Dijkstra/Dijkstra.txt: -------------------------------------------------------------------------------- 1 | 5 9 2 | 0 1 10 3 | 0 2 3 4 | 1 2 1 5 | 2 1 4 6 | 1 3 2 7 | 2 3 8 8 | 2 4 2 9 | 3 4 7 10 | 4 3 9 11 | -------------------------------------------------------------------------------- /99_others/ShortestPath/Dijkstra/Dijkstra_test.go: -------------------------------------------------------------------------------- 1 | package Diijkstra 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/mohuishou/algorithm/Graph" 8 | ) 9 | 10 | func TestDijkstra(t *testing.T) { 11 | graph := Graph.BuildGraph("Dijkstra.txt") 12 | path := make([]Graph.VextexType, graph.VNum) 13 | dist := make([]Graph.EdgeType, graph.VNum) 14 | Dijkstra(graph, 0, dist, path) 15 | tPath, err := GetPathForDijkstra(path, 1) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | checkDist := []Graph.EdgeType{0, 7, 3, 9, 5} 20 | checkPath := []Graph.VextexType{1, 2, 0} 21 | 22 | fmt.Println("expected dist is \t\t", checkDist) 23 | fmt.Println("the value of dist is \t\t", dist) 24 | fmt.Println("expected path is \t\t", checkPath) 25 | fmt.Println("the value of path is \t\t", tPath) 26 | 27 | if len(checkPath) != len(tPath) || len(dist) != len(checkDist) { 28 | t.Fail() 29 | } 30 | 31 | for i := len(checkPath) - 1; i >= 0; i-- { 32 | if checkPath[i] != tPath[i] { 33 | t.Fail() 34 | } 35 | } 36 | 37 | for i := len(dist) - 1; i >= 0; i-- { 38 | if checkDist[i] != dist[i] { 39 | t.Fail() 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /99_others/ShortestPath/Floyd/Floyd.go: -------------------------------------------------------------------------------- 1 | package Floyd 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/mohuishou/algorithm/GraphMatrix" 7 | ) 8 | 9 | //Floyd 求取多源最短路径 10 | func Floyd(graph GraphMatrix.Graph, dist [][]GraphMatrix.EdgeType, path [][]int) error { 11 | for i := 0; i < graph.VNum; i++ { 12 | for j := 0; j < graph.VNum; j++ { 13 | path[i][j] = -1 14 | dist[i][j] = graph.G[i][j] 15 | } 16 | } 17 | 18 | for k := 0; k < graph.VNum; k++ { 19 | for i := 0; i < graph.VNum; i++ { 20 | for j := 0; j < graph.VNum; j++ { 21 | 22 | //找到更短的路径 23 | if dist[i][k]+dist[k][j] < dist[i][j] { 24 | dist[i][j] = dist[i][k] + dist[k][j] 25 | 26 | //发现负值圈 27 | if i == j && dist[i][j] < 0 { 28 | return errors.New("存在负值圈") 29 | } 30 | path[i][j] = k 31 | } 32 | } 33 | } 34 | } 35 | return nil 36 | } 37 | 38 | //GetPathForFloyd 获取路径 39 | func GetPathForFloyd(path [][]int, s, t int) (tPath []int) { 40 | tPath = make([]int, 1) 41 | tPath[0] = s 42 | for { 43 | s = path[s][t] 44 | if s == -1 || s == t { 45 | tPath = append(tPath, t) 46 | return tPath 47 | } 48 | tPath = append(tPath, s) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /99_others/ShortestPath/Floyd/Floyd.txt: -------------------------------------------------------------------------------- 1 | 4 8 2 | 0 1 5 3 | 1 0 50 4 | 1 3 5 5 | 1 2 15 6 | 2 0 30 7 | 2 3 15 8 | 3 2 5 9 | 3 0 15 10 | -------------------------------------------------------------------------------- /99_others/ShortestPath/Floyd/Floyd_test.go: -------------------------------------------------------------------------------- 1 | package Floyd 2 | 3 | import ( 4 | "testing" 5 | 6 | "fmt" 7 | 8 | "github.com/mohuishou/algorithm/GraphMatrix" 9 | ) 10 | 11 | func TestFolyd(t *testing.T) { 12 | graph := GraphMatrix.BuildGraph("Floyd.txt") 13 | dist := make([][]GraphMatrix.EdgeType, graph.VNum) 14 | path := make([][]int, graph.VNum) 15 | for i := 0; i < graph.VNum; i++ { 16 | path[i] = make([]int, graph.VNum) 17 | dist[i] = make([]GraphMatrix.EdgeType, graph.VNum) 18 | } 19 | Floyd(graph, dist, path) 20 | 21 | fmt.Println("test result:") 22 | fmt.Print("source -> dest \t") 23 | fmt.Print("dist \t\t") 24 | fmt.Print("path \t\t\n") 25 | 26 | for i := 0; i < graph.VNum; i++ { 27 | for j := 0; j < graph.VNum; j++ { 28 | if i == j { 29 | continue 30 | } 31 | fmt.Print(i, " -> ", j, " \t\t") 32 | fmt.Print(dist[i][j], " \t\t") 33 | tPath := GetPathForFloyd(path, i, j) 34 | for i := 0; i < len(tPath); i++ { 35 | fmt.Print(tPath[i]) 36 | if i < len(tPath)-1 { 37 | fmt.Print("->") 38 | } 39 | } 40 | fmt.Print("\t\t\n") 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /99_others/ShortestPath/README.MD: -------------------------------------------------------------------------------- 1 | 最短路径问题 2 | ==== 3 | 4 | - Dijkstra 5 | - Floyd 6 | - SPFA -------------------------------------------------------------------------------- /99_others/ShortestPath/SPFA/SPFA.go: -------------------------------------------------------------------------------- 1 | package SPFA 2 | 3 | import ( 4 | "container/list" 5 | 6 | "errors" 7 | 8 | "github.com/mohuishou/algorithm/Graph" 9 | ) 10 | 11 | //INF 定义一个无穷大的数 12 | const INF = 0xfffff 13 | 14 | var ( 15 | graph Graph.Graph //图 16 | s Graph.VextexType //需要查找的顶点 17 | dist []Graph.EdgeType //各顶点到s的最短路径 18 | path []Graph.VextexType //路径集合 19 | visited []bool //标记顶点是否在队列当中 20 | count []int //统计,用于判断负环 21 | isInit bool //是否初始化 22 | ) 23 | 24 | //Init 初始化 25 | func Init(g Graph.Graph, S Graph.VextexType, Dist []Graph.EdgeType, Path []Graph.VextexType) { 26 | graph = g 27 | s = S 28 | dist = Dist 29 | path = Path 30 | //标记顶点是否在队列当中 31 | visited = make([]bool, graph.VNum) 32 | 33 | //统计,用于判断负环 34 | count = make([]int, graph.VNum) 35 | 36 | //初始化 37 | for i := 0; i < graph.VNum; i++ { 38 | dist[i] = INF //所有的dist为无穷远,即为不可达 39 | path[i] = -1 //所有的上级节点为-1,即为无上级节点 40 | visited[i] = false // 所有都尚未观察 41 | } 42 | 43 | //先将源点入队 44 | dist[s] = 0 45 | path[s] = s 46 | visited[s] = true 47 | count[s] = 1 48 | 49 | isInit = true 50 | } 51 | 52 | //DFS spfa算法dfs实现 53 | func DFS(u Graph.VextexType) error { 54 | if isInit != true { 55 | return errors.New("请先执行SPFA.Init方法") 56 | } 57 | visited[u] = true 58 | e := graph.G[u].FisrtEdge 59 | for e != nil { 60 | v := e.V 61 | if dist[v] > dist[u]+e.Weight { 62 | dist[v] = dist[u] + e.Weight //更新该点距离 63 | path[v] = u //更新父节点 64 | if visited[v] == false { 65 | count[v]++ 66 | if count[v] > graph.VNum { 67 | return errors.New("存在负环!") 68 | } 69 | 70 | //注意DFS的结果不能直接return,直接return的时候回溯的时候就没有办法在上一级重新找值了 71 | err := DFS(v) 72 | if err != nil { 73 | return err 74 | } 75 | } else { 76 | return nil 77 | } 78 | } 79 | e = e.Next 80 | } 81 | visited[u] = false 82 | return nil 83 | } 84 | 85 | //BFS spfa算法bfs实现,负环判断不太稳定 86 | func BFS() error { 87 | if isInit != true { 88 | return errors.New("请先执行SPFA.Init方法") 89 | } 90 | 91 | q := list.New() 92 | q.PushBack(s) 93 | 94 | //循环跳出条件:队列为空 95 | for q.Len() != 0 { 96 | u := q.Front().Value.(Graph.VextexType) 97 | q.Remove(q.Front()) 98 | 99 | //释放对点u的标记 100 | visited[u] = false 101 | 102 | e := graph.G[u].FisrtEdge 103 | 104 | for e != nil { 105 | //这条边下的顶点 106 | v := e.V 107 | 108 | //如果当前点的距离加上边的距离小于之前该点的距离,那么就更新该点的距离 109 | if dist[v] > dist[u]+e.Weight { 110 | dist[v] = dist[u] + e.Weight //更新该点距离 111 | path[v] = u //更新父节点 112 | 113 | //如果顶点不在队内,则将顶点入队 114 | if visited[v] == false { 115 | q.PushBack(v) //将该点入队 116 | visited[v] = true 117 | count[v]++ 118 | 119 | //出现负环,报错 120 | if count[v] > graph.VNum { 121 | return errors.New("存在负环!") 122 | } 123 | } 124 | } 125 | e = e.Next 126 | } 127 | 128 | } 129 | return nil 130 | } 131 | -------------------------------------------------------------------------------- /99_others/ShortestPath/SPFA/SPFA_test.go: -------------------------------------------------------------------------------- 1 | package SPFA 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/mohuishou/algorithm/Graph" 8 | ) 9 | 10 | func TestBFS(t *testing.T) { 11 | graph := Graph.BuildGraph("spfa.txt") 12 | path := make([]Graph.VextexType, graph.VNum) 13 | dist := make([]Graph.EdgeType, graph.VNum) 14 | Init(graph, 0, dist, path) 15 | err := BFS() 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | fmt.Println(dist) 20 | } 21 | 22 | func TestDFS(t *testing.T) { 23 | graph := Graph.BuildGraph("spfa.txt") 24 | path := make([]Graph.VextexType, graph.VNum) 25 | dist := make([]Graph.EdgeType, graph.VNum) 26 | Init(graph, 0, dist, path) 27 | err := DFS(s) 28 | if err != nil { 29 | t.Fatal(err) 30 | } 31 | 32 | fmt.Println(dist) 33 | } 34 | -------------------------------------------------------------------------------- /99_others/ShortestPath/SPFA/spfa.txt: -------------------------------------------------------------------------------- 1 | 5 9 2 | 0 1 10 3 | 0 2 3 4 | 1 2 1 5 | 2 1 4 6 | 1 3 2 7 | 2 3 8 8 | 2 4 2 9 | 3 4 7 10 | 4 3 9 11 | -------------------------------------------------------------------------------- /99_others/ShortestPath/doc.go: -------------------------------------------------------------------------------- 1 | // Package ShortestPath 最短路径算法实现 2 | // 包含三种常用的最短路径算法 3 | // Dijkstra算法 4 | // Floyd算法 5 | // SPFA算法 6 | package ShortestPath 7 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # Go 数据结构与算法系列 2 | 3 | > Go 数据结构与算法系列文章,本系列文章主要会包括常见的数据结构与算法实现,同时会包括 Go 标准库代码的分析理解,讲到对应章节的时候优先学习分析 Go 的源码实现,例如 slice、list、sort 等,然后可能会有一些常见的案例实现,同时这也是 极客时间-数据结构与算法之美 的课程笔记 4 | 5 | | 标题 | Github | 博客 | 6 | | ---- | --------- | ------------------------------------------------------------------------------------------------- | 7 | | 链表 | [list](./01_list) | [Go 数据结构与算法 01-链表(深入理解 container/list&LRU 缓存的实现)](https://lailin.xyz/post/list.html) | 8 | | 数组 | [array](./02_array) | [Go数据结构与算法02-数组: 深入理解 slice](https://lailin.xyz/post/array.html)
[Go数据结构与算法03-数组下: 使用 GDB 调试 Golang 代码](https://lailin.xyz/post/array_2.html) | 9 | | 栈 | [stack](./03_stack) | [Go数据结构与算法04-栈上: 如何实现一个计算器](https://lailin.xyz/post/stack.html)
[Go数据结构与算法05-栈下: 深入理解 defer](https://lailin.xyz/post/defer.html) | 10 | 11 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/go-algorithm 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/mohuishou/algorithm v0.0.0-20170417061216-79e9994e74e5 7 | github.com/stretchr/testify v1.6.1 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/mohuishou/algorithm v0.0.0-20170417061216-79e9994e74e5 h1:IVCUKsTr7l07IDF2sH/9NkYD7lvj+vul6G+yLNn+aQM= 4 | github.com/mohuishou/algorithm v0.0.0-20170417061216-79e9994e74e5/go.mod h1:xbrAXLmb467SPTTV211zL8r//shKKXzBiEPRnUHR7h0= 5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 8 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 9 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 10 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 11 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 12 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 13 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 14 | --------------------------------------------------------------------------------