DFS && BFS算法學習總結(jié)

兩種算法比較

  • 廣度優(yōu)先搜索一個圖的時候是按照樹的層次來搜索的,(層次遍歷),隊列來實現(xiàn),我們假設(shè)一個節(jié)點衍生出來的相鄰節(jié)點的平均個數(shù)是N個奋隶,那么當起點開始搜索的時候,隊列有一個節(jié)點唯欣,當起點拿出來后,把它相鄰的節(jié)點放進去搬味,那么隊列就有N個節(jié)點境氢,當下一層的搜索中再加入元素到隊列的時候,節(jié)點數(shù)達到了N2碰纬,你可以想想萍聊,一旦N是一個比較大的數(shù)的時候,這個樹的層次又比較深悦析,那這個隊列就得需要很大的內(nèi)存空間了脐区。
    缺點:在樹的層次較深&&子節(jié)點個數(shù)較多的情況下,消耗內(nèi)存現(xiàn)象十分嚴重她按。因此,BFS適用于節(jié)點的子節(jié)點個數(shù)不多炕柔,并且樹的層次不會太深的情況酌泰。優(yōu)點:可以得到最優(yōu)解。

  • 與上面相對應(yīng)的匕累,DFS可以克服這個缺點陵刹,因為每次搜索的時候只需要維護一個節(jié)點,(遞歸欢嘿、棧實現(xiàn))但回過頭想想衰琐,廣度優(yōu)先能夠找到最短路徑也糊,那深度優(yōu)先能否找到呢?深度優(yōu)先的方法是一條路走到黑羡宙,那顯然無法知道這條路是不是最短的狸剃,所以你還得繼續(xù)走別的路去判斷是否是最短路。
    缺點:難以尋找最優(yōu)解狗热,僅僅只能尋找有解钞馁。其優(yōu)點就是內(nèi)存消耗小,克服了剛剛說的廣度優(yōu)先搜索的缺點匿刮。

一般說來僧凰,能用DFS解決的問題都能用BFS解決。DFS通過遞歸實現(xiàn)熟丸,易于實現(xiàn)训措,DFS的常數(shù)時間開銷會比較少,所以大多數(shù)情況下優(yōu)先考慮DFS實現(xiàn)光羞。然后就是绩鸣,DFS容易棧溢出,而BFS可以自己控制隊列的長度狞山。最后全闷,BFS加上評估函數(shù)可以變成A算法,DFS加上評估函數(shù)可以變成IDA算法萍启。

DFS算法

核心思想

它的思想是從一個頂點V0開始总珠,沿著一條路一直走到底,如果發(fā)現(xiàn)不能到達目標解勘纯,那就返回到上一個節(jié)點局服,然后從另一條路開始走到底,這種盡量往深處走的概念即是深度優(yōu)先的概念驳遵。
代碼表示如下:

/**
 * DFS核心偽代碼
 * 前置條件是visit數(shù)組全部設(shè)置成false
 * @param n 當前開始搜索的節(jié)點
 * @param d 當前到達的深度
 * @return 是否有解
 */
bool DFS(Node n, int d){
    if (isEnd(n, d)){//一旦搜索深度到達一個結(jié)束狀態(tài)淫奔,就返回true
        return true;
    }

    for (Node nextNode in n){//遍歷n相鄰的節(jié)點nextNode
        if (!visit[nextNode]){//
            visit[nextNode] = true;//在下一步搜索中,nextNode不能再次出現(xiàn)
            if (DFS(nextNode, d+1)){//如果搜索出有解
                //做些其他事情堤结,例如記錄結(jié)果深度等
                return true;
            }

            //重新設(shè)置成false唆迁,因為它有可能出現(xiàn)在下一次搜索的別的路徑中
            visit[nextNode] = false;
        }
    }
    return false;//本次搜索無解

eg.二叉樹中和為某一值的路徑
題目描述
輸入一顆二叉樹和一個整數(shù),打印出二叉樹中結(jié)點值的和為輸入整數(shù)的所有路徑竞穷。路徑定義為從樹的根結(jié)點開始往下一直到葉結(jié)點所經(jīng)過的結(jié)點形成一條路徑唐责。

class Solution {
public:
     vector<vector<int>> res;
     vector<int> path;
    void find(TreeNode* root,  int sum)
    {
        if (root == NULL)return;
        path.push_back(root->val);
        if (!root->left && !root->right && sum == root->val)
            res.push_back(path);
        else
        {
            if (root->left)
                find(root->left, sum - root->val);
            if (root->right)
                find(root->right, sum - root->val);
        }
        path.pop_back();
    }
    vector<vector<int>> FindPath(TreeNode* root,int expectNumber) {
        find(root, expectNumber);
        return res;
    }
};

BFS算法

核心思想

廣度優(yōu)先搜索一個圖的時候是按照樹的層次來搜索的,(層次遍歷)瘾带,隊列來實現(xiàn)鼠哥,形象的說,這里有點像輻射形狀的搜索方式,從一個節(jié)點朴恳,向其旁邊節(jié)點傳遞病毒抄罕,就這樣一層一層的傳遞輻射下去,知道目標節(jié)點被輻射中了于颖,此時就已經(jīng)找到了從起點到終點的路徑呆贿。
核心代碼如下:

/**
 * 廣度優(yōu)先搜索
 * @param Vs 起點
 * @param Vd 終點
 */
bool BFS(Node& Vs, Node& Vd){
    queue<Node> Q;
    Node Vn, Vw;
    int i;

    //初始狀態(tài)將起點放進隊列Q
    Q.push(Vs);
    hash(Vw) = true;//設(shè)置節(jié)點已經(jīng)訪問過了!

    while (!Q.empty()){//隊列不為空恍飘,繼續(xù)搜索榨崩!
        //取出隊列的頭Vn
        Vn = Q.front();

        //從隊列中移除
        Q.pop();

        while(Vw = Vn通過某規(guī)則能夠到達的節(jié)點){
            if (Vw == Vd){//找到終點了!
                //把路徑記錄章母,這里沒給出解法
                return true;//返回
            }

            if (isValid(Vw) && !visit[Vw]){
                //Vw是一個合法的節(jié)點并且為白色節(jié)點
                Q.push(Vw);//加入隊列Q
                hash(Vw) = true;//設(shè)置節(jié)點顏色
            }
        }
    }
    return false;//無解
}   

對于一個題目來說母蛛,要標志節(jié)點是否訪問過,用數(shù)組是一種很快速的方法乳怎,但有時數(shù)據(jù)量太大彩郊,很難用一個大數(shù)組來記錄時,采用hash是最好的做法蚪缀。實際上visit數(shù)組在這里也是充當hash的作用秫逝。(PS:至于hash是什么?得自己去了解询枚,它的作用是在O(1)的時間復雜度內(nèi)取出某個值)

參考資料

深度優(yōu)先算法(DFS)
廣度優(yōu)先算法(BFS)
圖的基本算法
程序員必須知道的十大算法
圖的遍歷之DFS&BFS

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末违帆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子金蜀,更是在濱河造成了極大的恐慌刷后,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渊抄,死亡現(xiàn)場離奇詭異尝胆,居然都是意外死亡,警方通過查閱死者的電腦和手機护桦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門含衔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人二庵,你說我怎么就攤上這事贪染。” “怎么了催享?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵抑进,是天一觀的道長。 經(jīng)常有香客問我睡陪,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任兰迫,我火速辦了婚禮信殊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘汁果。我一直安慰自己涡拘,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布据德。 她就那樣靜靜地躺著鳄乏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪棘利。 梳的紋絲不亂的頭發(fā)上橱野,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音善玫,去河邊找鬼水援。 笑死,一個胖子當著我的面吹牛茅郎,可吹牛的內(nèi)容都是我干的蜗元。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼系冗,長吁一口氣:“原來是場噩夢啊……” “哼奕扣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起掌敬,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤惯豆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涝开,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體循帐,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年舀武,在試婚紗的時候發(fā)現(xiàn)自己被綠了拄养。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡银舱,死狀恐怖瘪匿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寻馏,我是刑警寧澤棋弥,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站诚欠,受9級特大地震影響顽染,放射性物質(zhì)發(fā)生泄漏漾岳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一粉寞、第九天 我趴在偏房一處隱蔽的房頂上張望尼荆。 院中可真熱鬧,春花似錦唧垦、人聲如沸捅儒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巧还。三九已至,卻和暖如春坊秸,著一層夾襖步出監(jiān)牢的瞬間麸祷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工妇斤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留摇锋,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓站超,卻偏偏與公主長得像荸恕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子死相,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

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

  • 因為之前就復習完數(shù)據(jù)結(jié)構(gòu)了融求,所以為了保持記憶,整理了一份復習綱要算撮,復習的時候可以看著綱要想具體內(nèi)容生宛。 樹 樹的基本...
    牛富貴兒閱讀 6,868評論 3 10
  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個結(jié)點至多有m個孩子。 除根結(jié)點和葉子結(jié)點外肮柜,其它每個結(jié)點至少有m...
    文檔隨手記閱讀 13,218評論 0 25
  • 課程介紹 先修課:概率統(tǒng)計陷舅,程序設(shè)計實習,集合論與圖論 后續(xù)課:算法分析與設(shè)計审洞,編譯原理莱睁,操作系統(tǒng),數(shù)據(jù)庫概論芒澜,人...
    ShellyWhen閱讀 2,279評論 0 3
  • 圖的表示 圖的記號是G = (V, E), 可以用兩種數(shù)據(jù)結(jié)構(gòu)表示: 鄰接鏈表和鄰接矩陣; note: 實際應(yīng)用中...
    陳碼工閱讀 918評論 0 2
  • 世人都知道泉孤是一代劍圣仰剿,卻不知他最擅長的其實是扇子,一把紙扇舞來了一個童養(yǎng)媳痴晦。 20歲的時候南吮,泉孤還沒有成為劍圣...
    即將變成瘦子閱讀 243評論 1 0