js尋路模式

關鍵詞:尋路

** 1.深度優先搜索(Depth-First-Search):**
沿著樹的深度遍歷樹的節點,盡可能深的搜索樹的分支。當節點v的所有邊都己被探尋過,搜索將回溯到發現節點v的那條邊的起始節點。這一過程一直進行到已發現從源節點可達的所有節點為止。如果還存在未被發現的節點,則選擇其中一個作為源節點并重復以上過程,整個進程反復進行直到所有節點都被訪問為止。DFS屬于盲目搜索。
利用深度優先搜索算法可以產生目標圖的相應拓撲排序表,利用拓撲排序表可以方便的解決很多相關的圖論問題,如最大路徑問題等等。一般用堆數據結構來輔助實現DFS算法。
步驟

  1. 訪問頂點v;
  2. 依次從v的未被訪問的鄰接點出發,對圖進行深度優先遍歷;直至圖中和v有路徑相通的頂點都被訪問;
  3. 若此時圖中尚有頂點未被訪問,則從一個未被訪問的頂點出發,重新進行深度優先遍歷,直到圖中所有頂點均被訪問過為止。
Paste_Image.png

對上面的圖G1進行深度優先遍歷,從頂點A開始。

Paste_Image.png

第1步:訪問A。
第2步:訪問(A的鄰接點)C。
在第1步訪問A之后,接下來應該訪問的是A的鄰接點,即"C,D,F"中的一個。但在本文的實現中,頂點ABCDEFG是按照順序存儲,C在"D和F"的前面,因此,先訪問C。
第3步:訪問(C的鄰接點)B。
在第2步訪問C之后,接下來應該訪問C的鄰接點,即"B和D"中一個(A已經被訪問過,就不算在內)。而由于B在D之前,先訪問B。
第4步:訪問(C的鄰接點)D。
在第3步訪問了C的鄰接點B之后,B沒有未被訪問的鄰接點;因此,返回到訪問C的另一個鄰接點D。
第5步:訪問(A的鄰接點)F。
前面已經訪問了A,并且訪問完了"A的鄰接點B的所有鄰接點(包括遞歸的鄰接點在內)";因此,此時返回到訪問A的另一個鄰接點F。
第6步:訪問(F的鄰接點)G。
第7步:訪問(G的鄰接點)E。

因此訪問順序是:A -> C -> B -> D -> F -> G -> E
下面以"有向圖"為例,來對深度優先搜索進行演示。

Paste_Image.png

對上面的圖G2進行深度優先遍歷,從頂點A開始。

Paste_Image.png

第2步:訪問B。
在訪問了A之后,接下來應該訪問的是A的出邊的另一個頂點,即頂點B。
第3步:訪問C。
在訪問了B之后,接下來應該訪問的是B的出邊的另一個頂點,即頂點C,E,F。在本文實現的圖中,頂點ABCDEFG按照順序存儲,因此先訪問C。
第4步:訪問E。
接下來訪問C的出邊的另一個頂點,即頂點E。
第5步:訪問D。
接下來訪問E的出邊的另一個頂點,即頂點B,D。頂點B已經被訪問過,因此訪問頂點D。
第6步:訪問F。
接下應該回溯"訪問A的出邊的另一個頂點F"。
第7步:訪問G。

因此訪問順序是:A -> B -> C -> E -> D -> F -> G


廣度優先搜索(Breadth-First-Search):
一種圖形搜索算法。簡單的說,BFS是從根節點開始,沿著樹(圖)的寬度遍歷樹(圖)的節點。如果所有節點均被訪問,則算法中止。BFS同樣屬于盲目搜索。一般用隊列數據結構來輔助實現BFS算法。
步驟:

  1. 首先將根節點放入隊列中。
  2. 從隊列中取出第一個節點,并檢驗它是否為目標。
    如果找到目標,則結束搜尋并回傳結果。
    否則將它所有尚未檢驗過的直接子節點加入隊列中。
  3. 若隊列為空,表示整張圖都檢查過了——亦即圖中沒有欲搜尋的目標。結束搜尋并回傳“找不到目標”。
  4. 重復步驟2。
Paste_Image.png

下面以"無向圖"為例,來對廣度優先搜索進行演示。還是以上面的圖G1為例進行說明。

Paste_Image.png

第1步:訪問A。
第2步:依次訪問C,D,F。
在訪問了A之后,接下來訪問A的鄰接點。前面已經說過,在本文實現中,頂點ABCDEFG按照順序存儲的,C在"D和F"的前面,因此,先訪問C。再訪問完C之后,再依次訪問D,F。
第3步:依次訪問B,G。
在第2步訪問完C,D,F之后,再依次訪問它們的鄰接點。首先訪問C的鄰接點B,再訪問F的鄰接點G。
第4步:訪問E。
在第3步訪問完B,G之后,再依次訪問它們的鄰接點。只有G有鄰接點E,因此訪問G的鄰接點E。

因此訪問順序是:A -> C -> D -> F -> B -> G -> E

下面以"有向圖"為例,來對廣度優先搜索進行演示。還是以上面的圖G2為例進行說明。


Paste_Image.png

第1步:訪問A。
第2步:訪問B。
第3步:依次訪問C,E,F。
在訪問了B之后,接下來訪問B的出邊的另一個頂點,即C,E,F。前面已經說過,在本文實現中,頂點ABCDEFG按照順序存儲的,因此會先訪問C,再依次訪問E,F。
第4步:依次訪問D,G。
在訪問完C,E,F之后,再依次訪問它們的出邊的另一個頂點。還是按照C,E,F的順序訪問,C的已經全部訪問過了,那么就只剩下E,F;先訪問E的鄰接點D,再訪問F的鄰接點G。

因此訪問順序是:A -> B -> C -> E -> F -> D -> G
啟發式搜索(Heuristically Search):
又稱為有信息搜索(Informed Search),它是利用問題擁有的啟發信息來引導搜索,達到減少搜索范圍、降低問題復雜度的目的,這種利用啟發信息的搜索過程稱為啟發式搜索。
就是在狀態空間中的搜索對每一個搜索的位置進行評估,得到最好的位置,再從這個位置進行搜索直到目標。
這樣可以省略大量無謂的搜索路徑,提高了效率。在啟發式搜索中,對位置的估價(估價函數)是十分重要的
利用啟發式搜索自動尋路實例

    <style type="text/css">
    *{ margin:0; padding:0;}
    li{ list-style:none;}
    #map{ 
        height:auto; 
        overflow:hidden; 
        margin:20px auto; 
        border:1px #ccc solid;     
        border-bottom:none; 
        border-right:none;
    }
    #map li{
        box-sizing: border-box;
        border:1px #ccc solid; 
        border-top:none; 
        border-left:none; 
        float:left;
    }
    #map li.sty1{ background:#e22841;}
    #map li.sty2{ background:orange;}
    #map li.sty3{ background:#00bcda;}
    #btn{ 
        width:160px; 
        height: 40px;
        color: #fff;
        text-align: center;
        line-height: 40px;
        font-size: 16px;
        background-color: #00bcda;
        border: none;
        border-radius: 5px;
        position:absolute; 
        left:0; 
        right: 0;
        margin: auto;
        cursor: pointer;
    }
    </style>

<body>
<ul id="map"></ul>
<span id="btn">快去解救公主!</span>
</body>
<script type="text/javascript">
var map = [
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,1,0,0,0,0,0,3,0,0,0,0,2,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,3,3,3,0,3,3,3,0,3,0,
    0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,3,3,0,3,3,3,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
];
var sizeGird = 24;  // 設定網格尺寸
var speed = 100;    // 設定移動速度

(function road(){
  var oUl = document.getElementById('map');
  var aLi = oUl.getElementsByTagName('li');
  var oBtn = document.getElementById('btn');
  var beginLi = oUl.getElementsByClassName('sty1');
  var endLi = oUl.getElementsByClassName('sty2');
  var cols = Math.sqrt(map.length);  
  var openArr = [];   // 存放可能要走的路線
  var closeArr = [];  // 存放不允許走的路線
  // 點擊按鈕初始化
  init();
  function init(){
    createMap();
    oBtn.onclick = function(){
        openFn();
    };
  }
  // 創建網格
  function createMap(){
    
    oUl.style.width = cols * (sizeGird) + 'px';
    
    for(var i=0;i<map.length;i++){
        var oLi = document.createElement('li');
        oLi.style.width = sizeGird + 'px';
        oLi.style.height = sizeGird + 'px';
        oUl.appendChild(oLi);
        
        if( map[i] == 1 ){
            oLi.className = 'sty1';
            openArr.push(oLi);
        }
        else if(map[i] == 2){
            oLi.className = 'sty2';
        }
        else if(map[i] == 3){
            oLi.className = 'sty3';
            closeArr.push(oLi);
        }
    }
  }

  function openFn(){
    var nowLi = openArr.shift();
    if( nowLi == endLi[0] ){
        showLine();
        return;
    }
    closeFn(nowLi);
    findLi(nowLi);
    //console.log( openArr );
    openArr.sort(function(li1,li2){
        return li1.num - li2.num;
    });
    //console.log( openArr );
    openFn();  // 遞歸操作,重復執行函數
  }
  // 過濾走過的路線
  function closeFn(nowLi){
    closeArr.push( nowLi );
  }
  // 找尋所有可能走的網格
  function findLi(nowLi){
    var result = [];
    for(var i=0;i<aLi.length;i++){
        if( filter(aLi[i]) ){
            result.push( aLi[i] );
    }
    }

    function filter(li){
        for(var i=0;i<closeArr.length;i++){
            if( closeArr[i] == li ){
                return false;
            }
        }
        for(var i=0;i<openArr.length;i++){
            if( openArr[i] == li ){
                return false;
            }
        }
        return true;
    }
    // 找到當前網格周圍的八個網格
    for(var i=0;i<result.length;i++){
        if( (Math.abs(nowLi.offsetLeft - result[i].offsetLeft)<= sizeGird) && (Math.  abs(nowLi.offsetTop - result[i].offsetTop)<= sizeGird) ){
            result[i].num = f(result[i]);
            result[i].parent = nowLi;
            openArr.push( result[i] );
        }
    }
  }
  // 顯示路線
  function showLine(){
    var result = [];
    var lastLi = closeArr.pop();
    var iNow = 0;
    findParent(lastLi);
    function findParent(li){
        result.unshift(li);
        if( li.parent == beginLi[0] ){
            return;
        }
        findParent(li.parent);
    }
    
    var timer = setInterval(function(){
        result[iNow].style.background = '#e22841';
        iNow++;
        if(iNow == result.length){
            clearInterval(timer);
        }
    },speed);
  }
  // 估價函數
  function f(nodeLi){
    return g(nodeLi) + h(nodeLi);
  }
  function g(nodeLi){
    var a = beginLi[0].offsetLeft - nodeLi.offsetLeft;
    var b = beginLi[0].offsetTop - nodeLi.offsetTop;
    return Math.sqrt(a*a + b*b);  // 利用了勾股定理
  }
  function h(nodeLi){
    var a = endLi[0].offsetLeft - nodeLi.offsetLeft;
    var b = endLi[0].offsetTop - nodeLi.offsetTop;
    return Math.sqrt(a*a + b*b);
  } 
})(map,sizeGird,speed)

在線預覽實例 ?[請點這里!!!][]
[請點這里!!!]:http://htmlpreview.github.io/?https://github.com/ferrinte/algorithm/blob/master/road.html


參考鏈接http://blog.csdn.net/yapian8/article/details/37809023

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • https://zh.visualgo.net/graphds 淺談圖形結構https://zh.visualgo...
    狼之獨步閱讀 4,230評論 0 0
  • 1. 關于診斷X線機準直器的作用,錯誤的是()。 (6.0 分) A. 顯示照射野 B. 顯示中心線 C. 屏蔽多...
    我們村我最帥閱讀 10,832評論 0 5
  • 作品《思月》獲陜西省首屆職工書畫大賽金獎。 作品《捧月》獲得云南世界博覽會優秀獎。中國美術家協會主辦。 作品《菊潭...
    塵埃里的草閱讀 198評論 0 0
  • 我是典型的三國迷,前日Down下FC的三國3-中原之霸者的ROM,就偷偷沉湎于三國世界。 十年前的老游戲了,熟...
    明哥明說閱讀 3,578評論 1 1
  • 黑板映照的日光,昏沉了整個夏季。白衣的少年,擾亂了一段青春。紛亂的思緒,落滿窗外的枝頭。 2017年10月15日,...
    風不喚閱讀 310評論 3 1