bfs.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // CookieJar - A contestant's algorithm toolbox
  2. // Copyright 2013 Peter Szilagyi. All rights reserved.
  3. //
  4. // CookieJar is dual licensed: use of this source code is governed by a BSD
  5. // license that can be found in the LICENSE file. Alternatively, the CookieJar
  6. // toolbox may be used in accordance with the terms and conditions contained
  7. // in a signed written agreement between you and the author(s).
  8. // Package bfs implements the breadth-first-search algorithm for the graphs.
  9. //
  10. // The BFS is implemented using on demand calculations, meaning that only that
  11. // part of the search space will be expanded as requested, iteratively expanding
  12. // it if needed.
  13. //
  14. // Neighbor traversal order currently is random due to the graph implementation.
  15. // Specific order may be added in the future.
  16. package bfs
  17. import (
  18. "gopkg.in/karalabe/cookiejar.v2/collections/queue"
  19. "gopkg.in/karalabe/cookiejar.v2/collections/stack"
  20. "gopkg.in/karalabe/cookiejar.v2/graph"
  21. )
  22. // Breadth-first-search algorithm data structure.
  23. type Bfs struct {
  24. graph *graph.Graph
  25. source int
  26. visited []bool
  27. parents []int
  28. order []int
  29. paths map[int][]int
  30. pending *queue.Queue
  31. builder *stack.Stack
  32. }
  33. // Creates a new random-order bfs structure.
  34. func New(g *graph.Graph, src int) *Bfs {
  35. d := new(Bfs)
  36. d.graph = g
  37. d.source = src
  38. d.visited = make([]bool, g.Vertices())
  39. d.visited[src] = true
  40. d.parents = make([]int, g.Vertices())
  41. d.order = make([]int, 1, g.Vertices())
  42. d.order[0] = src
  43. d.paths = make(map[int][]int)
  44. d.pending = queue.New()
  45. d.pending.Push(src)
  46. d.builder = stack.New()
  47. return d
  48. }
  49. // Generates the path from the source node to the destination.
  50. func (d *Bfs) Path(dst int) []int {
  51. // Return nil if not reachable
  52. if !d.Reachable(dst) {
  53. return nil
  54. }
  55. // If reachable, but path not yet generated, create and cache
  56. if cached, ok := d.paths[dst]; !ok {
  57. for cur := dst; cur != d.source; {
  58. d.builder.Push(cur)
  59. cur = d.parents[cur]
  60. }
  61. d.builder.Push(d.source)
  62. path := make([]int, d.builder.Size())
  63. for i := 0; i < len(path); i++ {
  64. path[i] = d.builder.Pop().(int)
  65. }
  66. d.paths[dst] = path
  67. return path
  68. } else {
  69. return cached
  70. }
  71. }
  72. // Checks whether a given vertex is reachable from the source.
  73. func (d *Bfs) Reachable(dst int) bool {
  74. if !d.visited[dst] && !d.pending.Empty() {
  75. d.search(dst)
  76. }
  77. return d.visited[dst]
  78. }
  79. // Generates the full order in which nodes were traversed.
  80. func (d *Bfs) Order() []int {
  81. // Force bfs termination
  82. if !d.pending.Empty() {
  83. d.search(-1)
  84. }
  85. return d.order
  86. }
  87. // Continues the bfs search from the last yield point, looking for dst.
  88. func (d *Bfs) search(dst int) {
  89. for !d.pending.Empty() {
  90. // Fetch the next node, and visit if new
  91. src := d.pending.Pop().(int)
  92. d.graph.Do(src, func(peer interface{}) {
  93. if p := peer.(int); !d.visited[p] {
  94. d.visited[p] = true
  95. d.order = append(d.order, p)
  96. d.parents[p] = src
  97. d.pending.Push(p)
  98. }
  99. })
  100. // If we found the destination, yield
  101. if dst == src {
  102. return
  103. }
  104. }
  105. }