F# 中的广度优先搜索 (BFS)

发布于 2024-11-08 00:44:01 字数 1222 浏览 6 评论 0原文

我想使用 BFS 实现搜索。该算法说我必须使用队列才能获得 FIFO 效果。 我读了 Chris Okasaki 的纯函数式数据结构一书,并找到了如何创建队列(我使用 F# 编写):

type 'a queue = 'a list * 'a list
let emtpy = [],[]
let isEmpty = function
    | [],_ -> true
    | _ -> false

let checkf = function
    | [],r -> List.rev r,[]
    | q -> q

let snoc (f,r) x = checkf (f,x :: r)

let head = function
    | ([],_) -> failwith "EMPTY"
    | (x::f,r) -> x

let tail = function
    | ([],_) -> failwith "EMPTY"
    | (x::f,r) -> checkf (f,r)

有人知道如何将其实现到 BFS 吗?

我有这个代码可以从列表中创建一棵树:(

let data = [4;3;8;7;10;1;9;6;5;0;2]

type Tree<'a> = 
    | Node of Tree<'a> * 'a * Tree<'a>
    | Leaf

let rec insert tree element = 
    match element,tree with
    | x,Leaf        -> Node(Leaf,x,Leaf)
    | x,Node(l,y,r) when x <= y -> Node((insert l x),y,r)
    | x,Node(l,y,r) when x > y -> Node(l,y,(insert r x))
    | _ -> Leaf

let makeTree = List.fold insert Leaf data

想要结合这两个代码)

I want to implement search using BFS. The Algorithm say that i must use a queue to get FIFO effect.
I read Chris Okasaki's Purely Functional Data Structures book and found how to make a queue (i wrote using F#) :

type 'a queue = 'a list * 'a list
let emtpy = [],[]
let isEmpty = function
    | [],_ -> true
    | _ -> false

let checkf = function
    | [],r -> List.rev r,[]
    | q -> q

let snoc (f,r) x = checkf (f,x :: r)

let head = function
    | ([],_) -> failwith "EMPTY"
    | (x::f,r) -> x

let tail = function
    | ([],_) -> failwith "EMPTY"
    | (x::f,r) -> checkf (f,r)

anyone know how to implement this to BFS?

and i have this code to make a tree from a list:

let data = [4;3;8;7;10;1;9;6;5;0;2]

type Tree<'a> = 
    | Node of Tree<'a> * 'a * Tree<'a>
    | Leaf

let rec insert tree element = 
    match element,tree with
    | x,Leaf        -> Node(Leaf,x,Leaf)
    | x,Node(l,y,r) when x <= y -> Node((insert l x),y,r)
    | x,Node(l,y,r) when x > y -> Node(l,y,(insert r x))
    | _ -> Leaf

let makeTree = List.fold insert Leaf data

(want to combine these two codes)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

平生欢 2024-11-15 00:44:01

BFS 算法是这样的:

Initialise the search by placing the starting vertex in the queue.
While the queue is not empty.
  Remove the front vertex from the queue.
  If this is a solution then we're finished -- report success.
  Otherwise, compute the immediate children of this vertex and enqueue them.
Otherwise we have exhausted the queue and found no solution -- report failure.

我的 F# 语法有点不稳定,但我将如何勾勒出解决方案:

bfs start = bfsLoop ([start], [])

bfsLoop q0 =
  if   isEmpty q0
  then failWith "No solution"
  else v = head q0
       if   isSolution v
       then v
       else q1 = tail q0
            vs = childrenOf v
            q = foldl snoc vs q1
            bfsLoop q

希望这会有所帮助。

the BFS algorithm is this:

Initialise the search by placing the starting vertex in the queue.
While the queue is not empty.
  Remove the front vertex from the queue.
  If this is a solution then we're finished -- report success.
  Otherwise, compute the immediate children of this vertex and enqueue them.
Otherwise we have exhausted the queue and found no solution -- report failure.

My F# syntax is a bit wobbly, but here's how I'd sketch out the solution:

bfs start = bfsLoop ([start], [])

bfsLoop q0 =
  if   isEmpty q0
  then failWith "No solution"
  else v = head q0
       if   isSolution v
       then v
       else q1 = tail q0
            vs = childrenOf v
            q = foldl snoc vs q1
            bfsLoop q

Hope this helps.

话少情深 2024-11-15 00:44:01

11年后可能还有用吗?

F# 中的 BFS 并不难:您可以使用递归来代替 while 循环来保持其不可变。

我将每个节点及其踪迹排入队列,以便我们可以计算解决方案路径。

let data = [4;3;8;7;10;1;9;6;5;0;2]

type Tree<'a> = 
    | Node of Tree<'a> * 'a * Tree<'a>
    | Leaf

let rec insert tree element = 
    match element,tree with
    | x,Leaf        -> Node(Leaf,x,Leaf)
    | x,Node(l,y,r) when x <= y -> Node((insert l x),y,r)
    | x,Node(l,y,r) when x > y -> Node(l,y,(insert r x))
    | _ -> Leaf

let tree = List.fold insert Leaf data

// BFS
let rec find goal queue =
  match queue with
  | []                          -> None
  | (Leaf, _)::tail             -> find goal tail
  | (Node (l,y,r), trace)::tail ->
    if y = goal then Some (List.rev (y::trace)) else
    find goal (tail @ [ l, y::trace; r, y::trace ])

// for example, to find the 5 in your tree
find 5 [tree, []]
|> printfn "%A"

// it will return: Some [4; 8; 7; 6; 5]
// because your tree looks like this:
//         4
//      /     \
//     3       8
//    /       / \
//   1       7   10
//  / \     /   /
// 0   2   6   9
//        /
//       5


Might still be useful 11 years later?

BFS in F# is not hard: Instead of a while loop you can use recursion to keep it mutable-free.

I enqueue each node with its trace so we can calculate the solution path.

let data = [4;3;8;7;10;1;9;6;5;0;2]

type Tree<'a> = 
    | Node of Tree<'a> * 'a * Tree<'a>
    | Leaf

let rec insert tree element = 
    match element,tree with
    | x,Leaf        -> Node(Leaf,x,Leaf)
    | x,Node(l,y,r) when x <= y -> Node((insert l x),y,r)
    | x,Node(l,y,r) when x > y -> Node(l,y,(insert r x))
    | _ -> Leaf

let tree = List.fold insert Leaf data

// BFS
let rec find goal queue =
  match queue with
  | []                          -> None
  | (Leaf, _)::tail             -> find goal tail
  | (Node (l,y,r), trace)::tail ->
    if y = goal then Some (List.rev (y::trace)) else
    find goal (tail @ [ l, y::trace; r, y::trace ])

// for example, to find the 5 in your tree
find 5 [tree, []]
|> printfn "%A"

// it will return: Some [4; 8; 7; 6; 5]
// because your tree looks like this:
//         4
//      /     \
//     3       8
//    /       / \
//   1       7   10
//  / \     /   /
// 0   2   6   9
//        /
//       5


~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文