搜索算法(Search)

1. 概述:
搜索算法是利用計算機的性能優點來有目的的枚舉一個問題解空間的部分或全部的可能狀況,從而求出問題的解的一種方法。在問題求解過程當中,人們所面臨的大多數現實問題每每沒有肯定性的算法,須要經過搜索算法來解決。
搜索問題通常只須要考慮兩個基本問題:
一、使用合適的狀態空間來表示問題。
二、測試該狀態空間中目標狀態是否會出現web

一個問題的基本信息由4部分組成
一、初始狀態集合—–>定義了問題的初始狀態
二、操做符集合—–>把一個問題從一個狀態轉換到另外一個狀態的動做集合
三、目標檢測函數—->用來肯定一個狀態是否是目標
四、路徑費用函數—->對每條路徑賦予必定費用的函數
其中,初始狀態集合和操做符集合定義了問題的搜索空間算法

搜索算法的兩個重要問題
搜索什麼和在哪裏搜索
所以搜索能夠被分爲兩個階段:狀態空間的生成階段和在該狀態空間中對所求問題的狀態的搜索
搜索能夠分爲啓發式搜索和盲目搜索svg

2. 盲目搜索:
通常是指從當前狀態到目標狀態須要走多少步或者每條路徑的花費並不知道,按照預約的搜索策略進行搜索,終止於目標狀態,因爲這種狀態沒有考慮到問題自己的特性,具備很大的盲目性,效率不高。須要提升盲目搜索的效率就須要尋找合理的搜索策略,該邊搜索順序
經常使用的盲目搜索有:深度優先搜搜(DFS)、廣度優先搜索(BFS)函數

一、深度優先搜索DFS
深度優先搜索沿着樹的深度遍歷樹的節點,儘量深的搜索樹的分支
當節點v的全部邊都已經被搜索過,將回溯到發現節點v的那條邊的起始節點
這一過程一直進行到已發現從源節點可達的全部節點爲止。
若是還存在未被發現的節點,則選擇其中一個做爲源節點並重覆上述過程
是一種典型的盲目搜索,若是不進行優化,DFS效率很低,通常要根據題意進行剪枝性能

DFS實現時通常用到遞歸,使用系統堆棧
void DFS(int v)
{
    visit(v);
    visited[i] = true;
    if (v和u存在邊 && !visited[u])
    {
        DFS(u); 
    }
}

二、廣度優先搜索BFS
是從任意節點V開始,一次搜索其能夠擴展的每個節點V1,V2。。。
當一層節點所有搜索完以後,再依次搜索第一個可擴展節點的全部節點
知道全部節點均被訪問,算法終止。
BFS和樹的層序遍歷很像,搜索順序具備明顯的層次性,通常用隊列實現
注意:先訪問頂點,再把頂點入隊,訪問完該頂點的全部鄰接頂點時,再出第一次訪問的節點,接下來就是重複上述步驟 測試

void BFS(int v)
{
    int w;
    visit(v);               //訪問頂點 
    visited[v] = true;      //頂點V對應的訪問標記置爲1
    queue.push_back(v);     //入隊
    while (!queue.Empty())
    {
        v = queue.pop_back();   //退出隊首元素
        w = firstAdj(v);        //求v的第一個鄰接點,無鄰接點時返回-1
        while (w != -1)
        {
            if (!visited[w])    //沒有訪問過該節點
            {
                visit(w);       //訪問該節點
                queue.push_back(w); //入隊
                visited[w] = true;  //標記置爲1 
            }
            w = nextAdj(v);         //求下一個鄰接點,無鄰接點時返回-1 
        }
    }
}

BFS經常使用於解決最優可行解的問題,相似最小步數、最短步數等優化

3. 啓發式搜索:
是在搜索過程當中加入了與問題有關的啓發式信息,用於指導搜索朝着最有但願的方向進行,掃除沒必要要的搜索過程,加速問題求解並獲得最優解。
因爲啓發式信息根據問題不一樣而異,所以須要分析問題的條件,尋找能夠改變搜索順序和剪枝的條件 ui