Scheme 语言 实战 Dijkstra 算法求解图最短路径问题

Schemeamuwap 发布于 2 天前 2 次阅读


Scheme 语言【1】实现 Dijkstra 算法【2】求解图最短路径问题

Dijkstra 算法是一种用于在加权图【4】中找到两点之间最短路径的算法。它由荷兰计算机科学家 Edsger Dijkstra 在 1959 年提出。Dijkstra 算法适用于单源最短路径问题【5】,即从单一源点出发,找到到达所有其他点的最短路径。

Scheme 语言是一种函数式编程语言【6】,以其简洁、优雅和可扩展性而闻名。我们将使用 Scheme 语言实现 Dijkstra 算法,并探讨其基本原理和实现细节。

Dijkstra 算法原理

Dijkstra 算法的基本思想是维护一个集合【7】,该集合包含所有已找到最短路径的顶点【8】,以及所有尚未找到最短路径的顶点。算法开始时,源点被添加到已找到集合【9】中,其余顶点被添加到未找到集合【10】中。然后,算法重复以下步骤:

1. 从未找到集合中选择一个顶点,该顶点的最短路径估计值【11】最小。
2. 将该顶点从未找到集合移动到已找到集合中。
3. 更新所有相邻顶点【12】的最短路径估计值。
4. 重复步骤 1-3,直到所有顶点都被添加到已找到集合中。

Scheme 语言实现

以下是使用 Scheme 语言实现的 Dijkstra 算法:

```scheme
(define (dijkstra graph【13】 source【14】)
(define (find-min-vertex【15】 unvisited【16】)
(let【17】 loop【18】 ((min-vertex (car【19】 unvisited))
(min-index 0)
(unvisited (cdr【20】 unvisited)))
(let ((new-min-vertex (car unvisited)))
(if (or (null?【21】 unvisited)
(< (get-distance【22】 graph min-vertex source)
(get-distance graph new-min-vertex source)))
(loop min-vertex min-index unvisited)
(loop new-min-vertex (+ min-index 1) unvisited)))))

(define (get-distance graph vertex1 vertex2)
(let ((edges【23】 (get-edges graph vertex1)))
(if (null? edges)
(error【24】 "Vertex not found")
(let loop ((edges edges)
(min-distance iinf【25】))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if ( (get-distance graph (car edge) source) new-distance)
(let ((new-unvisited (remove-vertex【26】 unvisited (car edge))))
(cons【27】 (cons (car edge) new-distance) new-unvisited))
unvisited)))

(define (get-edges graph vertex)
(let ((edges (graph vertex)))
(if (null? edges)
'()
(let loop ((edges edges)
(result '()))
(if (null? edges)
result
(let ((edge (car edges)))
(loop (cdr edges) (cons edge result))))))))

(define (get-distance graph vertex1 vertex2)
(let ((edges (get-edges graph vertex1)))
(if (null? edges)
(error "Vertex not found")
(let loop ((edges edges)
(min-distance iinf))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if ( (get-distance graph (car edge) source) new-distance)
(let ((new-unvisited (remove-vertex unvisited (car edge))))
(cons (cons (car edge) new-distance) new-unvisited))
unvisited)))

(define (get-edges graph vertex)
(let ((edges (graph vertex)))
(if (null? edges)
'()
(let loop ((edges edges)
(result '()))
(if (null? edges)
result
(let ((edge (car edges)))
(loop (cdr edges) (cons edge result))))))))

(define (get-distance graph vertex1 vertex2)
(let ((edges (get-edges graph vertex1)))
(if (null? edges)
(error "Vertex not found")
(let loop ((edges edges)
(min-distance iinf))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if ( (get-distance graph (car edge) source) new-distance)
(let ((new-unvisited (remove-vertex unvisited (car edge))))
(cons (cons (car edge) new-distance) new-unvisited))
unvisited)))

(define (get-edges graph vertex)
(let ((edges (graph vertex)))
(if (null? edges)
'()
(let loop ((edges edges)
(result '()))
(if (null? edges)
result
(let ((edge (car edges)))
(loop (cdr edges) (cons edge result))))))))

(define (get-distance graph vertex1 vertex2)
(let ((edges (get-edges graph vertex1)))
(if (null? edges)
(error "Vertex not found")
(let loop ((edges edges)
(min-distance iinf))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if ( (get-distance graph (car edge) source) new-distance)
(let ((new-unvisited (remove-vertex unvisited (car edge))))
(cons (cons (car edge) new-distance) new-unvisited))
unvisited)))

(define (get-edges graph vertex)
(let ((edges (graph vertex)))
(if (null? edges)
'()
(let loop ((edges edges)
(result '()))
(if (null? edges)
result
(let ((edge (car edges)))
(loop (cdr edges) (cons edge result))))))))

(define (get-distance graph vertex1 vertex2)
(let ((edges (get-edges graph vertex1)))
(if (null? edges)
(error "Vertex not found")
(let loop ((edges edges)
(min-distance iinf))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if ( (get-distance graph (car edge) source) new-distance)
(let ((new-unvisited (remove-vertex unvisited (car edge))))
(cons (cons (car edge) new-distance) new-unvisited))
unvisited)))

(define (get-edges graph vertex)
(let ((edges (graph vertex)))
(if (null? edges)
'()
(let loop ((edges edges)
(result '()))
(if (null? edges)
result
(let ((edge (car edges)))
(loop (cdr edges) (cons edge result))))))))

(define (get-distance graph vertex1 vertex2)
(let ((edges (get-edges graph vertex1)))
(if (null? edges)
(error "Vertex not found")
(let loop ((edges edges)
(min-distance iinf))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if ( (get-distance graph (car edge) source) new-distance)
(let ((new-unvisited (remove-vertex unvisited (car edge))))
(cons (cons (car edge) new-distance) new-unvisited))
unvisited)))

(define (get-edges graph vertex)
(let ((edges (graph vertex)))
(if (null? edges)
'()
(let loop ((edges edges)
(result '()))
(if (null? edges)
result
(let ((edge (car edges)))
(loop (cdr edges) (cons edge result))))))))

(define (get-distance graph vertex1 vertex2)
(let ((edges (get-edges graph vertex1)))
(if (null? edges)
(error "Vertex not found")
(let loop ((edges edges)
(min-distance iinf))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if ( (get-distance graph (car edge) source) new-distance)
(let ((new-unvisited (remove-vertex unvisited (car edge))))
(cons (cons (car edge) new-distance) new-unvisited))
unvisited)))

(define (get-edges graph vertex)
(let ((edges (graph vertex)))
(if (null? edges)
'()
(let loop ((edges edges)
(result '()))
(if (null? edges)
result
(let ((edge (car edges)))
(loop (cdr edges) (cons edge result))))))))

(define (get-distance graph vertex1 vertex2)
(let ((edges (get-edges graph vertex1)))
(if (null? edges)
(error "Vertex not found")
(let loop ((edges edges)
(min-distance iinf))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if ( (get-distance graph (car edge) source) new-distance)
(let ((new-unvisited (remove-vertex unvisited (car edge))))
(cons (cons (car edge) new-distance) new-unvisited))
unvisited)))

(define (get-edges graph vertex)
(let ((edges (graph vertex)))
(if (null? edges)
'()
(let loop ((edges edges)
(result '()))
(if (null? edges)
result
(let ((edge (car edges)))
(loop (cdr edges) (cons edge result))))))))

(define (get-distance graph vertex1 vertex2)
(let ((edges (get-edges graph vertex1)))
(if (null? edges)
(error "Vertex not found")
(let loop ((edges edges)
(min-distance iinf))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if ( (get-distance graph (car edge) source) new-distance)
(let ((new-unvisited (remove-vertex unvisited (car edge))))
(cons (cons (car edge) new-distance) new-unvisited))
unvisited)))

(define (get-edges graph vertex)
(let ((edges (graph vertex)))
(if (null? edges)
'()
(let loop ((edges edges)
(result '()))
(if (null? edges)
result
(let ((edge (car edges)))
(loop (cdr edges) (cons edge result))))))))

(define (get-distance graph vertex1 vertex2)
(let ((edges (get-edges graph vertex1)))
(if (null? edges)
(error "Vertex not found")
(let loop ((edges edges)
(min-distance iinf))
(if (null? edges)
min-distance
(let ((edge (car edges))
(new-distance (+ (get-distance graph vertex1 (car edge))
(cadr edge))))
(loop (cdr edges) (if (< new-distance min-distance) new-distance min-distance))))))))

(define (remove-vertex unvisited vertex)
(let loop ((unvisited unvisited)
(vertex vertex))
(if (null? unvisited)
unvisited
(let ((current-vertex (car unvisited)))
(if (eq? vertex current-vertex)
(cdr unvisited)
(loop (cdr unvisited) vertex)))))))

(define (update-distance【28】 graph unvisited min-vertex edge)
(let ((new-distance (+ (get-distance graph min-vertex source)
(cadr edge