js尋路模式

關(guān)鍵詞:尋路

** 1.深度優(yōu)先搜索(Depth-First-Search):**
沿著樹的深度遍歷樹的節(jié)點(diǎn),盡可能深的搜索樹的分支顽染。當(dāng)節(jié)點(diǎn)v的所有邊都己被探尋過睦刃,搜索將回溯到發(fā)現(xiàn)節(jié)點(diǎn)v的那條邊的起始節(jié)點(diǎn)辣卒。這一過程一直進(jìn)行到已發(fā)現(xiàn)從源節(jié)點(diǎn)可達(dá)的所有節(jié)點(diǎn)為止。如果還存在未被發(fā)現(xiàn)的節(jié)點(diǎn)隙姿,則選擇其中一個(gè)作為源節(jié)點(diǎn)并重復(fù)以上過程,整個(gè)進(jìn)程反復(fù)進(jìn)行直到所有節(jié)點(diǎn)都被訪問為止厂捞。DFS屬于盲目搜索输玷。
利用深度優(yōu)先搜索算法可以產(chǎn)生目標(biāo)圖的相應(yīng)拓?fù)渑判虮恚猛負(fù)渑判虮砜梢苑奖愕慕鉀Q很多相關(guān)的圖論問題靡馁,如最大路徑問題等等欲鹏。一般用堆數(shù)據(jù)結(jié)構(gòu)來輔助實(shí)現(xiàn)DFS算法。
步驟

  1. 訪問頂點(diǎn)v臭墨;
  2. 依次從v的未被訪問的鄰接點(diǎn)出發(fā)赔嚎,對(duì)圖進(jìn)行深度優(yōu)先遍歷;直至圖中和v有路徑相通的頂點(diǎn)都被訪問胧弛;
  3. 若此時(shí)圖中尚有頂點(diǎn)未被訪問尤误,則從一個(gè)未被訪問的頂點(diǎn)出發(fā),重新進(jìn)行深度優(yōu)先遍歷叶圃,直到圖中所有頂點(diǎn)均被訪問過為止袄膏。
Paste_Image.png

對(duì)上面的圖G1進(jìn)行深度優(yōu)先遍歷,從頂點(diǎn)A開始掺冠。

Paste_Image.png

第1步:訪問A沉馆。
第2步:訪問(A的鄰接點(diǎn))C码党。
在第1步訪問A之后,接下來應(yīng)該訪問的是A的鄰接點(diǎn)斥黑,即"C,D,F"中的一個(gè)揖盘。但在本文的實(shí)現(xiàn)中,頂點(diǎn)ABCDEFG是按照順序存儲(chǔ)锌奴,C在"D和F"的前面兽狭,因此,先訪問C鹿蜀。
第3步:訪問(C的鄰接點(diǎn))B箕慧。
在第2步訪問C之后,接下來應(yīng)該訪問C的鄰接點(diǎn)茴恰,即"B和D"中一個(gè)(A已經(jīng)被訪問過颠焦,就不算在內(nèi))。而由于B在D之前往枣,先訪問B伐庭。
第4步:訪問(C的鄰接點(diǎn))D。
在第3步訪問了C的鄰接點(diǎn)B之后分冈,B沒有未被訪問的鄰接點(diǎn)圾另;因此,返回到訪問C的另一個(gè)鄰接點(diǎn)D雕沉。
第5步:訪問(A的鄰接點(diǎn))F集乔。
前面已經(jīng)訪問了A,并且訪問完了"A的鄰接點(diǎn)B的所有鄰接點(diǎn)(包括遞歸的鄰接點(diǎn)在內(nèi))"蘑秽;因此饺著,此時(shí)返回到訪問A的另一個(gè)鄰接點(diǎn)F。
第6步:訪問(F的鄰接點(diǎn))G肠牲。
第7步:訪問(G的鄰接點(diǎn))E幼衰。

因此訪問順序是:A -> C -> B -> D -> F -> G -> E
下面以"有向圖"為例,來對(duì)深度優(yōu)先搜索進(jìn)行演示缀雳。

Paste_Image.png

對(duì)上面的圖G2進(jìn)行深度優(yōu)先遍歷渡嚣,從頂點(diǎn)A開始。

Paste_Image.png

第2步:訪問B肥印。
在訪問了A之后识椰,接下來應(yīng)該訪問的是A的出邊的另一個(gè)頂點(diǎn),即頂點(diǎn)B深碱。
第3步:訪問C腹鹉。
在訪問了B之后,接下來應(yīng)該訪問的是B的出邊的另一個(gè)頂點(diǎn)敷硅,即頂點(diǎn)C,E,F功咒。在本文實(shí)現(xiàn)的圖中愉阎,頂點(diǎn)ABCDEFG按照順序存儲(chǔ),因此先訪問C力奋。
第4步:訪問E榜旦。
接下來訪問C的出邊的另一個(gè)頂點(diǎn),即頂點(diǎn)E景殷。
第5步:訪問D溅呢。
接下來訪問E的出邊的另一個(gè)頂點(diǎn),即頂點(diǎn)B,D猿挚。頂點(diǎn)B已經(jīng)被訪問過咐旧,因此訪問頂點(diǎn)D。
第6步:訪問F绩蜻。
接下應(yīng)該回溯"訪問A的出邊的另一個(gè)頂點(diǎn)F"休偶。
第7步:訪問G。

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


廣度優(yōu)先搜索(Breadth-First-Search):
一種圖形搜索算法辜羊。簡(jiǎn)單的說,BFS是從根節(jié)點(diǎn)開始词顾,沿著樹(圖)的寬度遍歷樹(圖)的節(jié)點(diǎn)八秃。如果所有節(jié)點(diǎn)均被訪問,則算法中止肉盹。BFS同樣屬于盲目搜索昔驱。一般用隊(duì)列數(shù)據(jù)結(jié)構(gòu)來輔助實(shí)現(xiàn)BFS算法。
步驟:

  1. 首先將根節(jié)點(diǎn)放入隊(duì)列中上忍。
  2. 從隊(duì)列中取出第一個(gè)節(jié)點(diǎn)骤肛,并檢驗(yàn)它是否為目標(biāo)。
    如果找到目標(biāo)窍蓝,則結(jié)束搜尋并回傳結(jié)果腋颠。
    否則將它所有尚未檢驗(yàn)過的直接子節(jié)點(diǎn)加入隊(duì)列中。
  3. 若隊(duì)列為空吓笙,表示整張圖都檢查過了——亦即圖中沒有欲搜尋的目標(biāo)淑玫。結(jié)束搜尋并回傳“找不到目標(biāo)”。
  4. 重復(fù)步驟2面睛。
Paste_Image.png

下面以"無向圖"為例絮蒿,來對(duì)廣度優(yōu)先搜索進(jìn)行演示。還是以上面的圖G1為例進(jìn)行說明叁鉴。

Paste_Image.png

第1步:訪問A土涝。
第2步:依次訪問C,D,F。
在訪問了A之后幌墓,接下來訪問A的鄰接點(diǎn)但壮。前面已經(jīng)說過冀泻,在本文實(shí)現(xiàn)中,頂點(diǎn)ABCDEFG按照順序存儲(chǔ)的茵肃,C在"D和F"的前面腔长,因此,先訪問C验残。再訪問完C之后捞附,再依次訪問D,F。
第3步:依次訪問B,G您没。
在第2步訪問完C,D,F之后鸟召,再依次訪問它們的鄰接點(diǎn)。首先訪問C的鄰接點(diǎn)B氨鹏,再訪問F的鄰接點(diǎn)G欧募。
第4步:訪問E。
在第3步訪問完B,G之后仆抵,再依次訪問它們的鄰接點(diǎn)跟继。只有G有鄰接點(diǎn)E,因此訪問G的鄰接點(diǎn)E镣丑。

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

下面以"有向圖"為例舔糖,來對(duì)廣度優(yōu)先搜索進(jìn)行演示。還是以上面的圖G2為例進(jìn)行說明莺匠。


Paste_Image.png

第1步:訪問A金吗。
第2步:訪問B。
第3步:依次訪問C,E,F趣竣。
在訪問了B之后摇庙,接下來訪問B的出邊的另一個(gè)頂點(diǎn),即C,E,F遥缕。前面已經(jīng)說過卫袒,在本文實(shí)現(xiàn)中,頂點(diǎn)ABCDEFG按照順序存儲(chǔ)的单匣,因此會(huì)先訪問C玛臂,再依次訪問E,F。
第4步:依次訪問D,G封孙。
在訪問完C,E,F之后迹冤,再依次訪問它們的出邊的另一個(gè)頂點(diǎn)。還是按照C,E,F的順序訪問虎忌,C的已經(jīng)全部訪問過了泡徙,那么就只剩下E,F;先訪問E的鄰接點(diǎn)D膜蠢,再訪問F的鄰接點(diǎn)G堪藐。

因此訪問順序是:A -> B -> C -> E -> F -> D -> G
啟發(fā)式搜索(Heuristically Search):
又稱為有信息搜索(Informed Search)莉兰,它是利用問題擁有的啟發(fā)信息來引導(dǎo)搜索,達(dá)到減少搜索范圍礁竞、降低問題復(fù)雜度的目的糖荒,這種利用啟發(fā)信息的搜索過程稱為啟發(fā)式搜索。
就是在狀態(tài)空間中的搜索對(duì)每一個(gè)搜索的位置進(jìn)行評(píng)估模捂,得到最好的位置捶朵,再從這個(gè)位置進(jìn)行搜索直到目標(biāo)。
這樣可以省略大量無謂的搜索路徑狂男,提高了效率综看。在啟發(fā)式搜索中,對(duì)位置的估價(jià)(估價(jià)函數(shù))是十分重要的
利用啟發(fā)式搜索自動(dòng)尋路實(shí)例

    <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;  // 設(shè)定網(wǎng)格尺寸
var speed = 100;    // 設(shè)定移動(dòng)速度

(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 = [];  // 存放不允許走的路線
  // 點(diǎn)擊按鈕初始化
  init();
  function init(){
    createMap();
    oBtn.onclick = function(){
        openFn();
    };
  }
  // 創(chuàng)建網(wǎng)格
  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();  // 遞歸操作岖食,重復(fù)執(zhí)行函數(shù)
  }
  // 過濾走過的路線
  function closeFn(nowLi){
    closeArr.push( nowLi );
  }
  // 找尋所有可能走的網(wǎng)格
  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;
    }
    // 找到當(dāng)前網(wǎng)格周圍的八個(gè)網(wǎng)格
    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);
  }
  // 估價(jià)函數(shù)
  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)

在線預(yù)覽實(shí)例 ?[請(qǐng)點(diǎn)這里!!!][]
[請(qǐng)點(diǎn)這里!!!]:http://htmlpreview.github.io/?https://github.com/ferrinte/algorithm/blob/master/road.html


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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末红碑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子泡垃,更是在濱河造成了極大的恐慌析珊,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔑穴,死亡現(xiàn)場(chǎng)離奇詭異唾琼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)澎剥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赶舆,“玉大人哑姚,你說我怎么就攤上這事∈褪鳎” “怎么了夭问?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵尤莺,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我绞佩,道長(zhǎng),這世上最難降的妖魔是什么猪钮? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任品山,我火速辦了婚禮,結(jié)果婚禮上烤低,老公的妹妹穿的比我還像新娘肘交。我一直安慰自己,他們只是感情好扑馁,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布涯呻。 她就那樣靜靜地躺著凉驻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪复罐。 梳的紋絲不亂的頭發(fā)上涝登,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音效诅,去河邊找鬼胀滚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛填帽,可吹牛的內(nèi)容都是我干的蛛淋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼篡腌,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼褐荷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嘹悼,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤叛甫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后杨伙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體其监,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年限匣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抖苦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡米死,死狀恐怖锌历,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情峦筒,我是刑警寧澤究西,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站物喷,受9級(jí)特大地震影響卤材,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜峦失,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一扇丛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧尉辑,春花似錦晕拆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吝镣。三九已至,卻和暖如春昆庇,著一層夾襖步出監(jiān)牢的瞬間末贾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工整吆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拱撵,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓表蝙,卻偏偏與公主長(zhǎng)得像拴测,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子府蛇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • https://zh.visualgo.net/graphds 淺談圖形結(jié)構(gòu)https://zh.visualgo...
    狼之獨(dú)步閱讀 4,160評(píng)論 0 0
  • 1. 關(guān)于診斷X線機(jī)準(zhǔn)直器的作用集索,錯(cuò)誤的是()。 (6.0 分) A. 顯示照射野 B. 顯示中心線 C. 屏蔽多...
    我們村我最帥閱讀 10,558評(píng)論 0 5
  • 作品《思月》獲陜西省首屆職工書畫大賽金獎(jiǎng)汇跨。 作品《捧月》獲得云南世界博覽會(huì)優(yōu)秀獎(jiǎng)务荆。中國(guó)美術(shù)家協(xié)會(huì)主辦。 作品《菊潭...
    塵埃里的草閱讀 192評(píng)論 0 0
  • 我是典型的三國(guó)迷穷遂,前日Down下FC的三國(guó)3-中原之霸者的ROM函匕,就偷偷沉湎于三國(guó)世界。 十年前的老游戲了蚪黑,熟...
    明哥明說閱讀 3,513評(píng)論 1 1
  • 黑板映照的日光忌穿,昏沉了整個(gè)夏季抒寂。白衣的少年,擾亂了一段青春伴网。紛亂的思緒,落滿窗外的枝頭妆棒。 2017年10月15日澡腾,...
    風(fēng)不喚閱讀 298評(píng)論 3 1