简体   繁体   中英

Breadth first search on binary trees in OCaml using queues

I want to create a breadth-first search on binary trees in OCaml using queues, but I can't get it to work.

it seems like the function gets stuck when a node doesn't have any "neighbours".

let rec enque v l = 
    match l with
        [] -> [v]
    |   h::t -> h::(enque v t)



let rec qhd l =
    match l with
        h::[] -> h
    |   h::t -> qhd t



let deque l =
    match l with
        [] -> []
    |   h::t -> t



let notempty l = (l != [])


let rec breadthFirstHelp l =
    if notempty l
    then
        let cur = qhd l in
            match cur with
                Empty -> []
           |   (Node(Empty, node, Empty)) -> node::(breadthFirstHelp (deque l))
           |   (Node(left, node, right)) ->
               let l = enque right l in
               let l = enque left l in 
                   node::(breadthFirstHelp (deque l))
    else []

Here is a tree that I'm testing on.

[tree =
  Node
   (Node
     (Node (Empty, "A", Empty), "B",
      Node (Node (Empty, "C", Empty), "D", Empty)),
    "E", Node (Empty, "F", Node (Empty, "G", Node (Empty, "O", Empty))))]

With my code: ["E"; "B"; "A"; "A"; "A"]

Expected result: ["E"; "B"; "F"; "A"; "D"; "G"; "C"; "O"]

There are three problems in your code:

First, your qhd function is not compatible with your deque and enque function. Indeed, for a not empty queue q and a value any , one would expect that adding elements at the end of the queue does not change the element at the top:

 qhd q = qhd (enque any q)

whereas with your implementation for a queue q such that deque q is not empty, you have

 qhd q = qhd (deque q)

Second, in your breadthFirstHelp function, the empty case always returns [] even if there are pending subtrees in l .

Fixing those two issues should give you the right result, there is however a last performance issue: the enque function is very expansive because it needs to traverse the whole queue.

A simple solution is to split the list in two

  type 'a queue = { top: 'a list; bottom: 'a list }

when the bottom list is kept in reverse order. Thus appending to the queue is a matter of appending at the top of the bottom list. Whereas poping the queue requires only to take the first element of the top list if it is not empty, or to refill it from the bottom list otherwise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM