好的我有一个BFS的Lisp实现,我试图转换为进行爬山搜索。
以下是我的BFS代码:
; The list of lists is the queue that we pass BFS. the first entry and
; every other entry in the queue is a list. BFS uses each of these lists and
; the path to search.
(defun shortest-path (start end net)
(BFS end (list (list start)) net))
;We pass BFS the end node, a queue containing the starting node and the graph
;being searched(net)
(defun BFS (end queue net)
(if (null queue) ;if the queue is empty BFS has not found a path so exit
nil
(expand-queue end (car queue) (cdr queue) net)))
(defun expand-queue (end path queue net)
(let ((node (car path)))
(if (eql node end) ; If the current node is the goal node then flip the path
; and return that as the answer
(reverse path)
; otherwise preform a new BFS search by appending the rest of
; the current queue to the result of the new-paths function
(BFS end (append queue (new-paths path node net)) net))))
; mapcar is called once for each member of the list new-paths is passed
; the results of this are collected into a list
(defun new-paths (path node net)
(mapcar #'(lambda (n) (cons n path))
(cdr (assoc node net))))
现在,我知道我不需要像在BFS中一样扩展左边节点,而是需要扩展看起来最接近目标状态的节点。
我使用的图表如下所示:
(a (b 3) (c 1))
(b (a 3) (d 1))
我有一个转换函数,可以使用上面的BFS实现,但现在我需要使用这种图形格式将其转换为Hill攀爬。
我只是不确定从哪里开始,并且一直在尝试无济于事。我知道我主要需要更改expand-queue
函数来扩展最近的节点,但我似乎无法确定哪个节点最接近的函数。
感谢您的帮助!
答案 0 :(得分:0)
将事物附加到列表的末尾是错误的。这是列表中成本最高的操作。 复制整个列表,然后附加另一个列表。您可以在递归过程中使用它,这意味着每次扩展节点以创建新路径时都会执行此操作。
如果您将项目放在队列中,则需要查看您正在执行此操作的顺序。首先是广度,然后访问级别中的每个节点,然后再移动到下一级别。爬坡需要使用加权函数对候选人进行“最佳”排序。因此,您需要某种函数来计算当前节点和下一个候选节点的数值。然后,您需要对候选项进行排序,并首先扩展“最佳”节点。对于LIFO(后进先出)队列,这意味着最有希望的节点需要最后推送,因此它将是第一个被扩展的节点。请注意,LIFO队列非常适合单链接列表。 FIFO(先进先出)不是这样。
计算机科学的典型思想是数据抽象。如果LIFO QUEUE是这样的数据结构,则需要定义MAKE-LIFO-QUEUE,EMPTY-QUEUE-P等函数...然后使用这些函数而不是LIST,NULL和其他函数,它们的目的是数据结构更清晰。这会使您的代码更长,但由于Lisp列表是通用的并且可以(ab-)用于各种使用场景,因此单独查看列表操作并不能明确其意图。对于更复杂的图算法来说尤其重要。