C++ BFS实现

C++ BFS实现,c++,data-structures,graph-algorithm,breadth-first-search,C++,Data Structures,Graph Algorithm,Breadth First Search,我最近正在解决一个bfs问题,其中每个节点都是数组元素的不同排列。但我无法找到合适的数据结构来跟踪扩展树中访问的节点。通常,节点是不同的字符串,因此我们可以使用映射将节点标记为已访问,但在上述情况下,我应该使用什么DS?至少作为一个开始,您可以尝试使用/实现类似Java的array.toString()和映射。每种排列都会产生不同的字符串,因此它至少会有结果。至少作为一个开始,您可以尝试使用/实现Java的array.toString()之类的东西并使用映射。每种排列都会产生一个不同的字符串,因

我最近正在解决一个bfs问题,其中每个节点都是数组元素的不同排列。但我无法找到合适的数据结构来跟踪扩展树中访问的节点。通常,节点是不同的字符串,因此我们可以使用映射将节点标记为已访问,但在上述情况下,我应该使用什么DS?

至少作为一个开始,您可以尝试使用/实现类似Java的array.toString()和映射。每种排列都会产生不同的字符串,因此它至少会有结果。

至少作为一个开始,您可以尝试使用/实现Java的array.toString()之类的东西并使用映射。每种排列都会产生一个不同的字符串,因此它至少会有结果。

考虑以下伪代码:

type Node;  // information pertaining to a node
type Path;  // an ordered list of nodes
type Area;  // an area containing linked neighboring nodes
type Queue; // a FIFO queue structure

function Traverse(Area a, Node start, Node end) returns Path:
    Queue q;
    Node n;
                        // traverse backwards, from finish to start
    q.push(end);        // add initial node to queue
    end.parent = end;   // set first node's parent to itself

    while (not q.empty()):
        n = q.pop();    // remove first element

        if (n == start) // if element is the final element, we're done
            break;

        for (Node neighbor in a.neighbors(n)): // for each neighboring node
            if (neighbor.parent != Null):      // if already visited, skip
                continue;
            neighbor.parent = n;               // otherwise, visit 
            q.push(neighbor);                  // then add to queue

    Path p;             // prepare to build path from visited list

    for (Node previous = Null, current = n;
              previous != current;
              previous = current, current = current.parent):
        p.add(current); // for each node from start to end, add node to p
                        // Note that the first node's parent is itself
                        // thus dissatisfying the loop condition
    return p;
“已访问列表”存储为节点的父节点。将此编码为C++,您可能会将大部分节点作为引用或指针处理,因为该伪代码依赖于引用行为。 从一个区域开始,这是一个节点字段。该区域知道每个节点相对于其他节点的位置。您从一个特定的节点“开始”节点开始,并将其推送到队列中

遍历该区域非常简单,只需从该区域获取相邻节点的列表,如果它们已经被访问,则跳过它们,否则设置它们的父节点并将它们添加到队列中。当从队列中移除的节点等于目标节点时,遍历结束。您可以通过在邻居循环期间(最初遇到节点时)执行此检查来稍微加快算法的速度

注意:在开始遍历之前,不需要生成区域内所有可能的节点,该区域只需要在创建节点后跟踪节点。这可能有助于您使用字符串或数组排列的情况:您可以将起始节点和结束节点推入该区域,并且可以动态生成和缓存邻居节点。您可以将它们存储为向量,可以使用==运算符根据它们的顺序和内容进行相等性比较

遍历是向后的,而不是向前的,因为它使重建路径更容易(而不是在结束节点处结束,每个父节点在它之前,你在开始节点处结束,每个父节点在它之后)

数据结构摘要
节点
需要跟踪足够的信息,以便
区域
能够唯一地识别它(通过数组索引或名称等),以及父节点。在遍历之前,应该将父节点设置为NULL,以避免出现奇怪的行为,因为遍历将忽略具有父节点集的任何节点。这也会跟踪已访问状态:已访问相当于(parent!=NULL)。这样做还可以使您不必跟踪队列中的整个路径,这将非常需要计算

区域
需要维护一个
节点列表
,并且需要一个邻居映射,或者哪个节点与哪个其他节点相邻的映射。这种映射可能是通过函数动态生成的,而不是从表或其他更典型的方法中查找。它应该能够向调用者提供节点的邻居。有一个helper方法可以清除每个节点的父节点,这可能会有所帮助

Path
基本上是一种列表类型,包含节点的有序列表

队列
是任何可用的FIFO队列。你可以用一个链表


我喜欢在我的Wuggytovasp++上突出显示语法的方式。

考虑以下伪代码:

type Node;  // information pertaining to a node
type Path;  // an ordered list of nodes
type Area;  // an area containing linked neighboring nodes
type Queue; // a FIFO queue structure

function Traverse(Area a, Node start, Node end) returns Path:
    Queue q;
    Node n;
                        // traverse backwards, from finish to start
    q.push(end);        // add initial node to queue
    end.parent = end;   // set first node's parent to itself

    while (not q.empty()):
        n = q.pop();    // remove first element

        if (n == start) // if element is the final element, we're done
            break;

        for (Node neighbor in a.neighbors(n)): // for each neighboring node
            if (neighbor.parent != Null):      // if already visited, skip
                continue;
            neighbor.parent = n;               // otherwise, visit 
            q.push(neighbor);                  // then add to queue

    Path p;             // prepare to build path from visited list

    for (Node previous = Null, current = n;
              previous != current;
              previous = current, current = current.parent):
        p.add(current); // for each node from start to end, add node to p
                        // Note that the first node's parent is itself
                        // thus dissatisfying the loop condition
    return p;
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author VAISAKH N
 */
public class BFSME {

public static String path = "";
public static String add = "";

public static void findrec(String temp, String end, String[][] m, int j) {
    if (temp.equals(m[j][1])) {
        add = m[j][0] + temp + end + "/";
        end = temp + end;
        System.out.println(end);
        path = path + add;
        temp = "" + add.charAt(0);
        System.out.println("Temp" + temp);
        for (int k = 0; k < m.length; k++) {
            findrec(temp, end, m, k);
        }
    }
}

public static void main(String[] args) {

    String[][] data = new String[][]{{"a", "b"}, {"b", "c"}, {"b", "d"}, {"a", "d"}};
    String[][] m = new String[data.length][2];
    for (int i = 0; i < data.length; i++) {
        String temp = data[i][0];
        String end = data[i][1];
        m[i][0] = temp;
        m[i][1] = end;
        path = path + temp + end + "/";
        for (int j = 0; j < m.length; j++) {

            findrec(temp, end, m, j);
        }

    }
    System.out.println(path);
}
}
“已访问列表”存储为节点的父节点。将此编码为C++,您可能会将大部分节点作为引用或指针处理,因为该伪代码依赖于引用行为。 从一个区域开始,这是一个节点字段。该区域知道每个节点相对于其他节点的位置。您从一个特定的节点“开始”节点开始,并将其推送到队列中

遍历该区域非常简单,只需从该区域获取相邻节点的列表,如果它们已经被访问,则跳过它们,否则设置它们的父节点并将它们添加到队列中。当从队列中移除的节点等于目标节点时,遍历结束。您可以通过在邻居循环期间(最初遇到节点时)执行此检查来稍微加快算法的速度

注意:在开始遍历之前,不需要生成区域内所有可能的节点,该区域只需要在创建节点后跟踪节点。这可能有助于您使用字符串或数组排列的情况:您可以将起始节点和结束节点推入该区域,并且可以动态生成和缓存邻居节点。您可以将它们存储为向量,可以使用==运算符根据它们的顺序和内容进行相等性比较

遍历是向后的,而不是向前的,因为它使重建路径更容易(而不是在结束节点处结束,每个父节点在它之前,你在开始节点处结束,每个父节点在它之后)

数据结构摘要
节点
需要跟踪足够的信息,以便
区域
能够唯一地识别它(通过数组索引或名称等),以及父节点。在遍历之前,应该将父节点设置为NULL,以避免出现奇怪的行为,因为遍历将忽略具有父节点集的任何节点。这也会跟踪已访问状态:已访问相当于(parent!=NULL)。这样做还可以使您不必跟踪队列中的整个路径,这将非常需要计算

区域
需要维护
#include<iostream>
#include<bits/stdc++.h>
using namespace std;

//Adding node pair of a Edge in Undirected Graph 
void addEdge( vector<int> adj[], int u, int v){
    adj[u].push_back(v);  // 1st push_back
    adj[v].push_back(u);  //2nd push_back
    //for Directed Graph use only one push_back i.e., 1st push_back() rest is same 
}
//Traversing through Graph from Node 0 in Adjacency lists way
void showGraph( vector<int>adj[], int size){
    cout<<"Graph:\n";
    for(int i=0; i<size ; i++){
        cout<<i;
        for( vector<int>::iterator itr= adj[i].begin() ; itr!=adj[i].end(); itr++){
        cout<<" -> "<<*itr;
    }
    cout<<endl;
}
}
//Prints Array elements
void showArray(int A[]){
    for(int i=0; i< 6; i++){
        cout<<A[i]<<" ";
    }
}


void BFS( vector<int>adj[], int sNode, int N){

    //      Initialization
    list<int>queue; //Queue declaration
    int color[N]; //1:White, 2:Grey, 3:Black
    int parentNode[N];  //Stores the Parent node of that node while   traversing, so that you can reach to parent from child using this 
    int distLevel[N];   //stores the no. of edges required to reach the node,gives the length of path

    //Initialization
    for(int i=0; i<N; i++){
        color[i] = 1;   //Setting all nodes as white(1) unvisited
        parentNode[i] = -1;  //setting parent node as null(-1)
        distLevel[i] = 0;  //initializing dist as 0
    }

    color[sNode] = 2;  //since start node is visited 1st so its color is grey(2)
    parentNode[sNode] = -1;  //parent node of start node is null(-1)
    distLevel[sNode] = 0;    //distance is 0 since its a start node
    queue.push_back(sNode);  //pushing start node(sNode) is queue

    // Loops runs till Queue is not empty if queue is empty all nodes are visited
    while( !queue.empty()){

    int v = queue.front();  //storing queue's front(Node) to v
    // queue.pop_front();//Dequeue poping element from queue

    //Visiting all  nodes connected with v-node in adjacency list
    for(int i=0; i<adj[v].size() ;i++){

        if( color[ adj[v][i] ] == 1){// if node is not visited, color[node]==1  which is white 
            queue.push_back(adj[v][i]);  //pushing that node to queue
            color[adj[v][i]]=2;  //setting as grey(2)
            parentNode[ adj[v][i] ] = v; //parent node is stored                distLevel[ adj[v][i] ] = distLevel[v]+1;  //level(dist) is incremented y from dist(parentNode)
        }
    }//end of for
    color[v]=3;
    queue.pop_front();//Dequeue

}

printf("\nColor: \n");showArray(color);
printf("\nDistLevel:\n");showArray(distLevel);
printf("\nParentNode:\n");showArray(parentNode);
}

int main(){

int N,E,u,v;//no of nodes, No of Edges, Node pair for edge
cout<<"Enter no of nodes"<<endl;
cin>>N;
vector<int> adj[N];  //vector adjacency lists

cout<<"No. of edges"<<endl;
cin>>E;

cout<<"Enter the node pair for edges\n";
for( int i=0; i<E;i++){
    cin>>u>>v;
    addEdge(adj, u, v);  //invoking addEdge function
}

showGraph(adj,N);  //Printing Graph in Adjacency list format
BFS(adj,0,N);  /invoking BFS Traversal
}