A星進一步優化,讓二叉堆更快,更猛。as3版


二叉堆優化提高了A星一大步,但是想要更快,更猛,還不能停步。這兩天整理自己的A星,啃了些網上搜的一些大神源碼,今天整理下思路分享下。

A星原理和二叉優化在天地會文章很多,這里就不多說了,要讀此文先,提前是對A星有一定了解。(本文思路源於別人代碼,不是我原創,呵呵)

 

優化大多是用空間換時間,把過程的計算量放到初始存入內存。下面直接進入正題吧。

一、障礙鄰點的預計算。

判斷周圍格子是否有障礙還有計算格子的cost價值,如果在每次尋路的時候才去算就太浪費了,因為每次尋路的時候每個格子相鄰的障礙是不會變的,價值cost也不變,我們大可以把這塊計算抽出放到初始地圖的時候計算。步驟如下:

1.給節點添加鄰節點數組nodeLinks,和鄰節點價值組costLinks。(也可建一個linkNode對象,對象里面有節點和價值兩屬性,反正兩數組是個映對關系),保證nodeLinks[i]的價值是costLinks[i]

2.地圖初始好的時候遍歷每個格子,計算出其周圍的所有非障礙的格子,並加入節點鄰數組中存起。計算每個鄰節點的價值,映對存入節點價值組。

3.尋路的時候判斷節點四周有哪些格子直接從當前計算的節點的nodeLinks屬性取即可,不需要再計算。

預計算可節省很多性能,不過缺點是初始的時候很慢。 

 

二、Array數組優化

Array的indexOf和shift方法是很吃性能的,很多人的A星在while里面有這兩個東西,這是那幾百毫秒慢下的原因。懷疑的同學可以自己寫個1萬次的大循環調用這兩個方法看看。要判斷節點是否在開戶組里面,普通人的做法是用indexOf,其實這個方式可以換成以下處理

1.給節點添加isOpen:Boolean屬性

2.每次push節點到打開數組的里面設節點的isOpen為true

3.節點移出打開列表時,將節點的isOpen屬性設為false

4.判斷節點是否在開啟列表時只需要判斷isOpen即可

判斷關閉同理,另外還有會用上indexOf的地方是二叉堆里面,干掉方式略。

將關閉組添加到通過父節點添加到返回路徑時,很多人會用shift,把節點一個個添到path數組里面,這也是個慢的因素。可以換成push方式,push不會改變索引,所以效率很高。將關閉節點組數據通過push加入路徑后,再調用reverse把數組倒置,結果跟用shift一樣,不過用時可大不一樣。

 

三、打開關閉標記,換掉不用重置

用isOpen來替代indexOf大大提升了一步性能,可是每次尋路完之后會有個問題,那就是要把節點重置,就是把所有打開和關閉列表里面的節點的isOpen,isClose設false。呵呵,雖然這個重置吃的性能相當小,不過本着追求精神,我又找出了更變態的方式。步驟如下

1.每次A星計算設一唯一自增標記markIndex,每計算一次尋路,這個整型屬性+1

2.把節點里面的isOpen和isClose布爾屬性改成openMark,closeMark整型屬性。

3.加入列表時把openmark設為本次計算的自動標記markIndex,移出列表設為-1(或隨便一個不等於markIndex的數)

4.判斷是否在打開列表中只需判斷if(openMark==markIndex)即可

5.某次尋路計算完之后markIndex+1

因為自增標記每次計算都不一樣,所以節點的openMark不需要重置,下次也能繼續用。這個方式帶來的性能提升很微小不多,不追求那幾十毫秒的大可無視。

 

四、減少while里面get/set/function

get/set的性能其實很高,不過在項目中,大量的格子一經過while方法就是數萬次的運算,雖然每次性能相差很少,但量一大起來效率就明顯了。不信的人可以寫個大循環在里面用getter和public屬性的方式對比一下,性能相差三四倍。如果節點的f,g,h,x,y這些屬性用了接口get/set,那個運算毫秒相差就很明顯了。function 是代碼設計不可省的東西,這一步優化只適合在A星的while中用,正常項目中可省不得。

 

五、位運算,再提一提微小的性能

在二叉堆中的除以2,num/2==num*0.5==num >> 1,這三個種計算方式最快的明顯是第三種,雖然可讀性差些,不過效率還是有點提升滴。另外num*2 == num<<1;也可提升些性能

 

目前能想到的提速度方法就這樣,先開篇日記記錄一下,以后找到新的再補。源碼還沒整理好,暫時先這么上了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM