《图的深度优先搜索和广度优先搜索》

版权声明:copyright@xxdk2017 https://blog.csdn.net/u011583798/article/details/78452928

1. 代码

/************************************************************************* 
    > File Name: dfsbfs.cpp 
    > Author: XXDK 
    > Email: [email protected]  
    > Created Time: Sun 05 Nov 2017 09:53:40 PM CST 
 ************************************************************************/  
#include<iostream>  
#include<list>  
#include<vector>  
#include<queue>  
#include<stack>  
#include<fstream>  
#include<cstring>  
/*
>>>> extract from Algorithms Fourth Edition:

As implied at the outset, DFS and BFS are the first of several instances that we will
examine of a general approach to searching graphs. We put the source vertex on the
data structure, then perform the following steps until the data structure is empty:
	■ Take the next vertex v from the data structure and mark it.
	■ Put onto the data structure all unmarked vertices that are adjacent to v.
The algorithms differ only in the rule used to take the next vertex from the data structure
(least recently added for BFS, most recently added for DFS). This difference leads to completely
different views of the graph, even though all the vertices and edges connected to the source are
examined no matter what rule is used.

DFS wends its way through the graph, storing on the stack the points where other
paths branch off; BFS sweeps through the graph, using a queue to remember
the frontier of visited places. DFS explores the graph by looking for new
vertices far away from the start point, taking closer vertices only when dead
ends are encountered; BFS completely covers the area close to the starting
point, moving farther away only when everything nearby has been examined.
DFS paths tend to be long and winding; BFS paths are short and direct.
Depending upon the application, one property or the other may be desirable
(or properties of paths may be immaterial)
*/
using namespace std;  
typedef vector< list<int> > Graph;  
  
int vertexs;  
int edgeTo[100] = {0};     // last vertex on known path to this vettex
bool marked[100] = {0};  // is a shortest path to this vertex known?

Graph graph;  
stack<int> path;
  
void CreateGraphFromConsole()  
{  
    int degree;  
    cout << "input the vertex num: " << endl;  
    cin >> vertexs;  
  
    for (int i = 0; i < vertexs; ++i) {  
        int t;  
        list<int> i1;  
        cout << "input the vertex["<< i << "] degree and adjacent vertexs: ";  
        cin >> degree;  
        for(int j = 0; j < degree && cin >> t; j++) {   
            i1.push_back(t);  
        }  
  
        graph.push_back(i1);  
    }  
}  

/* ------------------- 
 * vertexs count 
 * ------------------- 
 * vertexs degree  | adjacent vertexs  
 * */  
void CreateGraphFromFile()  
{  
    int degree;  
    ifstream in("data.txt");  
  
    in >> vertexs;  
    for (int i = 0; i < vertexs; ++i) {  
        list<int> i1;  
        int t;  
        in >> degree;  
  
        for(int j = 0; j < degree && in >> t; j++) {   
            i1.push_back(t);  
        }  
        graph.push_back(i1);  
    }  
}  

void PrintGraph(Graph& graph)  
{  
    Graph::iterator it;  
  
    for (int i = 0; i < vertexs; ++i) {  
        list<int> i1 = graph[i];  
        list<int>::iterator it;  
        cout << "vertex["<< i << "]: ";  
        for(it = graph[i].begin(); it != graph[i].end(); it++) {   
            cout << *it <<"->";  
        }  
        cout << "NULL"<< endl;  
  
        graph.push_back(i1);  
    }  
}  
/*
 * use a implicit stack provided by recursion.
 * */ 
void dfs(int start)   
{  
    list<int>::iterator it;  
    marked[start] = true;  
    cout << start << " ";  

    for (it = graph[start].begin(); it != graph[start].end(); it++) {
        if (!marked[*it]) {
			edgeTo[*it] = start;
            dfs(*it);  
		}
	}
}  

/*
 * use a explicit stack.
 * */ 
void dfs_noRecursion(int start)  
{  
    list<int>::iterator it;  
    marked[start] = true;  
    cout << start << " ";  
    stack<int> mystack;  
    mystack.push(start);  
  
    while (!mystack.empty()) {  
        start = mystack.top();  
        mystack.pop();  
        if (!marked[start]) {  
            cout << start << " ";  
            marked[start] = true;  
        }  
  
		// 对该顶点的邻接表的所有顶点遍历
        for (it = graph[start].begin(); it != graph[start].end(); it++) {  
			// 如果含有未被访问标记过的顶点
            if (!marked[*it]) {  
				// 标识访问该顶点时所出发的(最近)顶点;
				edgeTo[*it] = start;
				// 将未被访问标记过的顶点入栈
                mystack.push(*it);  
            }  
        }  
    }  
}  

/* 
 * use a explicit queue.
 * edgeTo[]: a parent-link representation of a tree 
 * rooted at start, which defines the shortest paths 
 * form start to every vertex that is connected to s.
 */
void bfs(int start)  
{  
    list<int>::iterator it;  
    marked[start] = true;  
    cout << start << " ";  
    queue<int> myque;  

    myque.push(start);  
    while (!myque.empty()) {  
        start = myque.front();  
        myque.pop();  
		// for every unmarked adjacent vertex. 
        for (it = graph[start].begin(); it != graph[start].end(); it++) {  
            if (!marked[*it]) {  
                cout << *it << " ";  
				// save last edge on a shortest path
				edgeTo[*it] = start;
				// add it to the queue
                myque.push(*it);  
				// mark it because path is known
                marked[*it] = true;      
            }  
        }  
    }  
}  
/**********************************************************
 * 如果一个顶点被访问标记过, 说明一定存在到该顶点的路径
 **********************************************************/
bool HasPathTo(int vertex)
{
	return marked[vertex];
}

/**********************************************************
 * 从顶点start到end的路径, 注意这里的PathTo方法调用之前
 * 必须确保已经执行过从顶点start开始的bfs或dfs方法
 **********************************************************/
void PathTo(int start, int end) 
{
	if(!HasPathTo(end)) 
		return ;

	for(int x = end; x != start; x = edgeTo[x])
		path.push(x);
	path.push(start);
	cout << endl;
	cout << "path form "<< start << " to " << end <<": ";
	int s;
	while(!path.empty()) {
		s = path.top();  
		cout << s << " ";
		path.pop();  
	}
    cout << endl;  
}

int main()  
{  
    CreateGraphFromFile();  
    PrintGraph(graph);  
  
    cout << "result for bfs:" << endl;  
    bfs(0);  
	PathTo(0, 4);

	cout << endl;
    memset(marked, 0, sizeof(marked));  
    memset(edgeTo, 0, sizeof(edgeTo));  
    cout << "result for dfs(Recursion):" << endl;  
    dfs(0);  
	PathTo(0, 4);
  
	cout << endl;
    memset(marked, 0, sizeof(marked));  
    memset(edgeTo, 0, sizeof(edgeTo));  
    cout << "result for dfs(no Recursion):" << endl;  
    dfs_noRecursion(0);  
	PathTo(0, 4);
  
    return 0;  
}  



 


2. data.txt

6
3 1 2 3
2 0 3
2 0 3
4 1 0 2 5
1 5 
2 3 4



猜你喜欢

转载自blog.csdn.net/u011583798/article/details/78452928