📜  最佳优先搜索(知情搜索)

📅  最后修改于: 2021-04-27 18:57:24             🧑  作者: Mango

先决条件:BFS,DFS
在BFS和DFS中,当我们在一个节点上时,可以将任何相邻节点视为下一个节点。因此,BFS和DFS都在不考虑任何成本函数的情况下盲目探索路径。最佳优先搜索的想法是使用评估函数来确定哪个最有前途,然后再进行探索。最佳优先搜索属于“启发式搜索”或“知情搜索”类别。

我们使用优先级队列来存储节点成本。因此,实现是BFS的变体,我们只需要将Queue更改为PriorityQueue。

// This pseudocode is adapted from below 
// source:
// https://courses.cs.washington.edu/
Best-First-Search(Grah g, Node start)
    1) Create an empty PriorityQueue
       PriorityQueue pq;
    2) Insert "start" in pq.
       pq.insert(start)
    3) Until PriorityQueue is empty
          u = PriorityQueue.DeleteMin
          If u is the goal
             Exit
          Else
             Foreach neighbor v of u
                If v "Unvisited"
                    Mark v "Visited"                    
                    pq.insert(v)
             Mark u "Examined"                    
End procedure

让我们考虑以下示例。

BFS

We start from source "S" and search for
goal "I" using given costs and Best
First search.

pq initially contains S
We remove s from and process unvisited
neighbors of S to pq.
pq now contains {A, C, B} (C is put
before B because C has lesser cost)

We remove A from pq and process unvisited
neighbors of A to pq.
pq now contains {C, B, E, D}

We remove C from pq and process unvisited
neighbors of C to pq.
pq now contains {B, H, E, D}

We remove B from pq and process unvisited
neighbors of B to pq.
pq now contains {H, E, D, F, G}

We remove H from pq.  Since our goal
"I" is a neighbor of H, we return.

下面是上述想法的实现:

C++
// C++ program to implement Best First Search using priority
// queue
#include 
using namespace std;
typedef pair pi;
 
vector > graph;
 
// Function for adding edges to graph
void addedge(int x, int y, int cost)
{
    graph[x].push_back(make_pair(cost, y));
    graph[y].push_back(make_pair(cost, x));
}
 
// Function For Implementing Best First Search
// Gives output path having lowest cost
void best_first_search(int source, int target, int n)
{
    vector visited(n, false);
    // MIN HEAP priority queue
    priority_queue, greater > pq;
    // sorting in pq gets done by first value of pair
    pq.push(make_pair(0, source));
    visited = true;
 
    while (!pq.empty()) {
        int x = pq.top().second;
        // Displaying the path having lowest cost
        cout << x << " ";
        pq.pop();
        if (x == target)
            break;
 
        for (int i = 0; i < graph[x].size(); i++) {
            if (!visited[graph[x][i].second]) {
                visited[graph[x][i].second] = true;
                pq.push(graph[x][i]);
            }
        }
    }
}
 
// Driver code to test above methods
int main()
{
    // No. of Nodes
    int v = 14;
    graph.resize(v);
 
    // The nodes shown in above example(by alphabets) are
    // implemented using integers addedge(x,y,cost);
    addedge(0, 1, 3);
    addedge(0, 2, 6);
    addedge(0, 3, 5);
    addedge(1, 4, 9);
    addedge(1, 5, 8);
    addedge(2, 6, 12);
    addedge(2, 7, 14);
    addedge(3, 8, 7);
    addedge(8, 9, 5);
    addedge(8, 10, 6);
    addedge(9, 11, 1);
    addedge(9, 12, 10);
    addedge(9, 13, 2);
 
    int source = 0;
    int target = 9;
 
    // Function call
    best_first_search(source, target, v);
 
    return 0;
}


Python
from queue import PriorityQueue
v = 14
graph = [[] for i in range(v)]
 
# Function For Implementing Best First Search
# Gives output path having lowest cost
 
 
def best_first_search(source, target, n):
    visited = [0] * n
    visited = True
    pq = PriorityQueue()
    pq.put((0, source))
    while pq.empty() == False:
        u = pq.get()[1]
        # Displaying the path having lowest cost
        print(u, end=" ")
        if u == target:
            break
 
        for v, c in graph[u]:
            if visited[v] == False:
                visited[v] = True
                pq.put((c, v))
    print()
 
# Function for adding edges to graph
 
 
def addedge(x, y, cost):
    graph[x].append((y, cost))
    graph[y].append((x, cost))
 
 
# The nodes shown in above example(by alphabets) are
# implemented using integers addedge(x,y,cost);
addedge(0, 1, 3)
addedge(0, 2, 6)
addedge(0, 3, 5)
addedge(1, 4, 9)
addedge(1, 5, 8)
addedge(2, 6, 12)
addedge(2, 7, 14)
addedge(3, 8, 7)
addedge(8, 9, 5)
addedge(8, 10, 6)
addedge(9, 11, 1)
addedge(9, 12, 10)
addedge(9, 13, 2)
 
source = 0
target = 9
best_first_search(source, target, v)
 
# This code is contributed by Jyotheeswar Ganne


输出
0 1 3 2 8 9 

分析 :

  • 最佳优先搜索的最坏情况时间复杂度是O(n * Log n),其中n是节点数。在最坏的情况下,我们可能必须先访问所有节点,然后才能达到目标。请注意,优先级队列是使用最小(或最大)堆实现的,插入和删除操作需要O(log n)时间。
  • 算法的性能取决于设计成本或评估函数的程度。