用scheme語言實現SPFA演算法(單源最短路)

2021-07-08 15:32:04 字數 4523 閱讀 9875

最近自己陷入了很長時間的學習和思考之中,突然發現好久沒有更新博文了,於是便想更新一篇。

這篇文章是我之前程式語言課作業中一段**,用scheme語言實現單源最段路演算法。當時的我,花了一整天時間,學習了scheme並實現了spfa演算法,那天實現之後感覺很有成就感~在這裡貼出來,以饗讀者。

突然發現不支援scheme語言,於是只能放棄高亮了。不得不說,scheme**有沒有高亮差別好大……

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;; 題目:單源最短路,輸入資料給定

;;;; 學號:5130309680

;;;; 演算法:spfa(簡化版)

;;;; **結構:共三大部分——

;; 開始是一些語法糖,

;; 然後是spfa演算法的實現,

;; 最後是主體部分,呼叫了spfa演算法並輸出結果。

;;;; 備註:**備註共有兩種——

;; 1. **的三大部分,各自開頭有一段備註

;; 2. **的兩個主體部分,內部穿插了一些備註

;; 其中,兩個主體部分是指:**主體部分 以及 spfa演算法的主體部分(即spfa函式)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(begin

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;; 這裡是為後面**定義的一些語法糖。

;;;; 為了可讀性,我做了乙個「下標變換」:

;; 題目圖中6個點,儲存為0~5,但供操作的api對外設計成1~6的假象,簡化思路

;;;; 有一維陣列、二維陣列、佇列和邏輯運算幾方面,具體如下所示:

;; 1. 根據下標該值,構造新陣列:change, change2

;; 2. 根據下標賦值(+下標變換):set, set2

;; 3. 根據下標取值(+下標變換):get, get2

;; 4. 入隊、出隊:push, pop

;; 5. 邏輯運算(二元與、二元或):and, or

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define (change a i x)

(if (eqv? i 0)

(cons x (cdr a))

(cons (car a) (change (cdr a) (- i 1) x))))

(define (change2 a i j x)

(if (eqv? i 0)

(cons (change (car a) j x) (cdr a))

(cons (car a) (change2 (cdr a) (- i 1) j x))))

(define-syntax set

(syntax-rules ()

([set a i x] (set! a (change a (- i 1) x)))))

(define-syntax set2

(syntax-rules ()

([set2 a i j x]

(begin

(set! a (change2 a (- i 1) (- j 1) x))

(set! a (change2 a (- j 1) (- i 1) x))))))

(define-syntax get

(syntax-rules ()

([get a i] (list-ref a (- i 1)))))

(define-syntax get2

(syntax-rules ()

([get2 a i j] (list-ref (list-ref a (- i 1)) (- j 1)))))

(define-syntax push

(syntax-rules ()

(define-syntax pop

(syntax-rules ()

([pop q]

(let ([x (car q)])

(set! q (cdr q))

x))))

(define-syntax and

(syntax-rules ()

([and ea eb]

(if (eqv? ea #t)

(if (eqv? eb #t) #t #f)

#f))))

(define-syntax or

(syntax-rules ()

([or ea eb]

(if (eqv? ea #t)

#t(if (eqv? eb #t) #t #f)))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;; 此為spfa演算法部分(簡化版)

;;;; 其中spfa函式是主體,其呼叫了update-all函式,後者又呼叫了update函式。

;;;; 注:之所以稱之為簡化版,是因為本來spfa的入隊應該去重的,但被我給省了。

;; 不過本題中並不要求速度、也不影響正確性,寫不寫也就無所謂了。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define (update map d q u allv)

(cond

[(not (eqv? allv null))

(let ([v (car allv)] [lastv (cdr allv)])

; (newline)

; (display "an update --") (newline)

; (display "d: ") (display d) (newline)

; (display "q: ") (display q) (newline)

; (display "u: ") (display u) (newline)

; (display "v: ") (display v) (newline)

; (display "allv: ") (display allv) (newline)

(cond

[(and (not (eqv? (get2 map u v) #f)) (or (eqv? (get d v) #f) (< (+ (get d u) (get2 map u v)) (get d v))))

(begin

(set d v (+ (get d u) (get2 map u v)))

(push q v))])

(update map d q u lastv))]

[else (list d q)]))

(define (update-all map d q)

(if (eqv? q null)

d (let ([u (pop q)])

(define tmp (update map d q u (list 1 2 3 4 5 6)))

(set! d (car tmp))

(set! q (cadr tmp))

(update-all map d q))))

(define (spfa map s)

; 初始化spfa中的陣列

(define d (make-list 6 #f))

(set d s 0)

(define q null)

(push q s)

; 輸出初始化的陣列,僅供除錯

(display "d: ") (display d) (newline)

(display "q: ") (display q) (newline)

; 計算由s出發的單源最短路,並返回計算出的結果

(update-all map d q))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;; 題目主函式在此

;;;; 本題所有的io都在這裡給出了,一目了然。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; 建圖 稱為map

(define map (make-list 6 (make-list 6 #f)))

(set2 map 1 2 7)

(set2 map 1 3 9)

(set2 map 1 6 14)

(set2 map 2 4 15)

(set2 map 2 3 10)

(set2 map 3 4 11)

(set2 map 3 6 2)

(set2 map 4 5 6)

(set2 map 5 6 9)

; 通過簡化的spfa演算法計算最短路

(define d (spfa map 1))

; 輸出答案

(display "last-d: ") (display d) (newline)

(display "result: ") (display (get d 5)) (newline))

用C語言實現FlappyBird

在開始遊戲之前,我們先了解一些輔助函式 void gotoxy int x,int y 將游標調整到 x,y 的位置 void hidecursor 隱藏游標 setconsolecursorinfo getstdhandle std output handle cursor info 我們使用乙個...

用c語言實現佇列 FIFO

佇列是一種先進先出的資料結構,它的儲存表示方式有兩種 順序儲存和鏈式儲存 順序儲存由於要考慮假溢位的情況,所以採用迴圈佇列形式 c語言實現 define queuesize 100 定義佇列的大小 typedef int datatype 定義佇列元素型別 typedef struct circle...

用C語言實現(掃雷遊戲)

include include include include pragma warning disable 4996 define rows 8 define cols 8 define mines 62 void menu 列印選單 void init mine char mine cols 2...