转自:http://lingyibin.javaeye.com/blog/849828
我想大部分人都用Floyd或者Dijstra算法,甚至dfs算过最短路吧。
其实BFS也可以计算最短路。(补充:本文只针对无权图,有权图很难用BFS)
当我们用BFS找端对端最短路时,从出发点开始,第一次遍历到终点时过的那条路径就是最短的路径。(读者可以思考一下为什么!)
下面就用邻接表来实现一下BFS最短路,并把路径打出来。
- #include<iostream>
- #include<fstream>
- #include<queue>
- using namespace std;
-
- const int MAX = 50;
-
- struct link
- {
- int data;
- link *next;
- };
- struct Node
- {
- int v;
- link *next;
- };
- struct Graph
- {
- Node node[MAX+1];
- int nodeCnt;
- };
-
- int visited[MAX+1];
- int pa[MAX+1];
-
-
- Graph readGraph()
- {
- ifstream cin("c://graph.txt");
-
-
- Graph graph;
- int i ;
- for(i = 1; i < MAX; i ++)
- {
- graph.node[i].v = i;
- graph.node[i].next = NULL;
- }
-
- int n1 = 0,n2 = 0;
- link *s;
- graph.nodeCnt = 1;
- while(cin>>n1>>n2)
- {
- if(graph.nodeCnt < n1) graph.nodeCnt=n1;
- if(graph.nodeCnt < n2) graph.nodeCnt=n2;
- s = new link;
- s->data = n2;
- s->next=graph.node[n1].next;
- graph.node[n1].next=s;
-
-
- s=new link;
- s->data = n1;
- s->next=graph.node[n2].next;
- graph.node[n2].next=s;
-
- }
- return graph;
- }
-
-
- void printGraph(Graph graph)
- {
- link *p;
- for(int i = 1; i <= graph.nodeCnt; i ++)
- {
- cout<<graph.node[i].v<<" -- ";
-
- p=graph.node[i].next;
- while(p!=NULL)
- {
- cout<<p->data;
- p=p->next;
- if(p != NULL)
- cout<<",";
- }
- cout<<endl;
- }
- }
-
-
- void shortestPath(Graph graph, int s, int d)
- {
- cout<<"从"<<s<<"到"<<d<<"的bfs最短路求解过程如下:"<<endl;
- queue<int> que ;
- link * p = NULL;
-
- int parents = s;
- memset(visited,0,sizeof(visited));
- memset(pa,0,sizeof(pa));
- visited[s] = 1;
- pa[s] = -1;
- que.push(s);
- while(!que.empty()){
- p = graph.node[que.front()].next;
- parents = que.front();
- que.pop();
-
- while(p != NULL)
- {
- if(!visited[p->data])
- {
- visited[p->data] = 1;
- pa[p->data] = parents;
- cout<<"访问:"<<p->data<<endl;
- if(p->data == d)
- {
-
- break;
- }
- que.push(p->data);
- }
- p = p->next;
- }
- }
- cout<<"路径如下:"<<endl;
- parents = d;
-
- while(pa[parents] != -1)
- {
- cout<<parents<<" <- ";
- parents = pa[parents];
- }
- cout<<parents<<endl;
- }
-
- int main()
- {
- int s,d;
- Graph graph = readGraph();
- printGraph(graph);
- while(true)
- {
- cout<<"请输入起点和终点:"<<endl;
- cin>>s>>d;
- shortestPath(graph, s , d);
- }
- return 0;
- }
#include<iostream>
#include<fstream>
#include<queue>
using namespace std;
const int MAX = 50;
struct link
{
int data;
link *next;
};
struct Node
{
int v; //顶点相关的信息
link *next;
};
struct Graph
{
Node node[MAX+1]; //所有的结点
int nodeCnt; //用来记录图中结点的数目,这里假设用的是连通图。假设不连通,稍微改一下本程序就行了,具体操作留给读者思考!
};
int visited[MAX+1]; //标志数组
int pa[MAX+1];
/* 读取文件中的数据,构造一个邻接表来表示图 */
Graph readGraph()
{
ifstream cin("c://graph.txt");
//表的初始化
Graph graph;
int i ;
for(i = 1; i < MAX; i ++)
{
graph.node[i].v = i;
graph.node[i].next = NULL;
}
int n1 = 0,n2 = 0;
link *s;
graph.nodeCnt = 1;//把结点数初始化为1
while(cin>>n1>>n2)
{
if(graph.nodeCnt < n1) graph.nodeCnt=n1;
if(graph.nodeCnt < n2) graph.nodeCnt=n2;
s = new link;
s->data = n2;
s->next=graph.node[n1].next;
graph.node[n1].next=s; //从尾部插入
//delete(s);
s=new link;
s->data = n1;
s->next=graph.node[n2].next;
graph.node[n2].next=s; //反过来也赋值,说明本程序测试的是无向图,如果是有向图的话读者应该知道怎么改了吧!
//delete(s);
}
return graph;
}
/* 打印邻接表 */
void printGraph(Graph graph)
{
link *p;
for(int i = 1; i <= graph.nodeCnt; i ++)
{
cout<<graph.node[i].v<<" -- ";
p=graph.node[i].next;
while(p!=NULL)
{
cout<<p->data;
p=p->next;
if(p != NULL)
cout<<",";
}
cout<<endl;
}
}
/* 用BFS求最短路径 */
void shortestPath(Graph graph, int s, int d)
{
cout<<"从"<<s<<"到"<<d<<"的bfs最短路求解过程如下:"<<endl;
queue<int> que ;
link * p = NULL;
//int cnt = 0;
int parents = s;
memset(visited,0,sizeof(visited));
memset(pa,0,sizeof(pa));
visited[s] = 1;
pa[s] = -1;
que.push(s);
while(!que.empty()){
p = graph.node[que.front()].next;
parents = que.front();
que.pop();
//cnt ++;
while(p != NULL)
{
if(!visited[p->data])
{
visited[p->data] = 1;
pa[p->data] = parents;
cout<<"访问:"<<p->data<<endl;
if(p->data == d) //找到了目标结点
{
//cout<<"在第"<<cnt<<"层找到目标结点!(出发点算第一层)"<<endl;
break;
}
que.push(p->data);
}
p = p->next;
}
}
cout<<"路径如下:"<<endl;
parents = d;
//cout<<parents<<" <- ";
while(pa[parents] != -1)
{
cout<<parents<<" <- ";
parents = pa[parents];
}
cout<<parents<<endl;
}
int main()
{
int s,d;
Graph graph = readGraph();
printGraph(graph);
while(true)
{
cout<<"请输入起点和终点:"<<endl;
cin>>s>>d;
shortestPath(graph, s , d);
}
return 0;
}
输入文件graph.txt里数据格式如下: