F#实现图的广度遍历
继上一篇的深度遍历,下面实现以下图的广度遍历,广度遍历中使用到了队列, 即代码中的
let nodesQueue = new Queue<Node>(),由于F# 中没有指针,如果我们需要在递归中保存一个随时会发生变化的值时,我会选择ref类型的变量。
下面顺便说说ref类型变量的一些基本操作:
let x = ref 1
定义一个ref类型的变量
let getValue = !x
!x用来获取此ref变量的值,这里将其值赋给了getValue变量
x := 2
将x 的值变为2
let newValue = !x
这里,变量newValue的值就是2了。
接下来就是此遍历的具体代码了,没有什么新的东西:)
type GraphOperations(graph : Graph) = member this.BFSTraverse(action : unit -> unit, startNodeId : string, endNodeId : string) = let visited : string array = Array.zeroCreate graph.Nodes.Length let visitIndex = ref 0 //queue of visited nodes let nodesQueue = new Queue<Node>() let startNode = ref Unchecked.defaultof<Node> try startNode := graph.Nodes |> List.find(fun item -> item.ID = startNodeId) with | _ -> printfn "There is no such node" nodesQueue.Enqueue(!startNode) if ((!startNode).ID = endNodeId) then action()//defined by user, what you want to do when find the target? else visited.[!visitIndex] <- (!startNode).ID visitIndex := !visitIndex + 1 while(nodesQueue.Count <> 0) do let node = nodesQueue.Dequeue() let adjNodes = node.OutgoingEdges |> List.map(fun xNode -> xNode.ToNode) let freshAdjNodes = adjNodes |> List.filter(fun adjnode ->not (visited |> Array.exists(fun x -> x = adjnode.ID))) let mutable foundFlag = false let index = ref 0 while (!index < freshAdjNodes.Length && foundFlag = false) do if(freshAdjNodes.[!index].ID = endNodeId) then action() foundFlag <- true else visited.[!visitIndex] <- freshAdjNodes.[!index].ID visitIndex := !visitIndex + 1 nodesQueue.Enqueue(freshAdjNodes.[!index]) index := !index + 1
留个笔记~:)