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

1. 代码

/************************************************************************* 
    > File Name: dfsbfs.cpp 
    > Author: XXDK 
    > Email: v.manstein@qq.com  
    > 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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值