图的遍历
题目描述
利用邻接表或邻接矩阵存储图,并对图进行深度和广度优先遍历。
(1)定义图的邻接表或邻接矩阵存储;
(2)利用邻接表(或邻接矩阵)存储图;(参考图的邻接矩阵存储表示或图的邻接表存储表示)
(3)对图进行深度优先遍历;
(4)对图进行广度优先遍历;
(5)比较图的深度优先遍历和广度优先遍历两种遍历方法的不同及其时间和空间复杂度。
算法描述
(1)函数名:add()
输入:int a,int b;
功能:建立邻接表
输出:无
算法:用数组模拟邻接表
(2)函数名:floyd()
输入:无
功能:利用floyd算法
求最短距离
输出:无
算法:动态规划,状态转移程: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]}
(3)函数名:Bft(int t1)
输入:int t1
功能:1/广度优先遍历
2/利用广度优先遍历输出各节点度数
输出:2/输出各节点度数
算法:宽度优先遍历
(4)函数名:Dft(int u,int v,string str,int len,int res )
输入:int u,int v,string str,int len,int res
功能:1/深度优先遍历
2/得到两节点全部简单路径
3/得到两节点长度为len的全部简单路径
输出:2/输出两节点全部简单路径
3/输出两节点长度为len的全部简单路径
算法:深度优先搜索
(5)函数名:Time_Complexity_Comparison()
输入:无
功能:比较深搜与宽搜 的时间复杂度
输出:输出比较结果
算法:无
(6)函数名:Get_Number_Of_Sides_Per_Point()
输入:无
功能:调用bft()函数的第二个功能
输出:输出每个节点的度数
算法:利用一个for循环完成遍历
(7)函数名:Judging_The_Existence_Of_Edges()
输入:无
功能:判断两个节点是否联通
输出:输出判断结果
算法:判断g[u][v]是不是等于0
(8)函数名:Determine_The_Simple_Path()
输入:无
功能:计算得到点u到v的所有的简单路径
输出:输出点u到v的所有的简单路径
算法:利用dfs进行在遍历的时候完成查找计算
(9)函数名:Output_Simple_Path()
输入:无
功能:得到点u到v的所有长度为length的所有的简单路径
输出:输出点u到v的所有长度 为length的所有的简单路径
算法:利用dfs第三个功能
(11)函数名:Find_The_Shortest_Path()
输入:无
功能:求不带权的无向连通图中顶点u到v的一条最短简单路径
输出:判断结果
算法:调用floyd函数
(12)函数名:Menu1()
输入:无
功能:完成各种输入
输出:无
算法:无
(13)函数名:Menu2()
输入:无
功能:消息循环函数
输出:无
算法:无
流程图
运行结果
Menu1( )
bft()
dft()
Judging_The_Existence_Of_Edges()
Get_Number_Of_Sides_Per_Point()
Determine_The_Simple_Path()
Output_Simple_Path( )
Find_The_Shortest_Path( )
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<windows.h>
//有向图
using namespace std;
const int N = 510,INF = 0x3f3f3f3f;
int h[N],ne[N],e[N],data[N],idx;
int g[N][N];//邻接矩阵
int q[N];//队列
int d[N];//顶点的度
int dist[N][N];
int st[N];
int n,m;
int v;
bool it;
/**************
函数名:add()
输入:int a,int b;
功能:建立邻接表
输出:无
**************/
void add(int a,int b,int c) //邻接表
{
ne[idx] = h[a],e[idx] = b,data[idx] = c , h[a] = idx++;
}
/**************
函数名:floyd()
输入:无
功能:利用floyd算法
求最短距离
输出:无
**************/
int floyd()
{
for(int k = 1; k <= n ; k ++ )
for(int i = 1; i <= n ; i ++ )
for(int j = 1; j <= n; j ++ )
dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]);
}
/**************
函数名:Bft(int t1)
输入:int t1
功能:1/广度优先遍历
2/利用广度优先遍历
输出各节点度数
输出:2/输出各节点度数
**************/
void Bft(int t1)
{
memset(st,1,sizeof st);
int hh = 0 ,tt = -1;
q[++tt] = 1;
st[1]=0;
if(t1) cout <<"顶点 "<< 1 << " 的度数为 "<< d[1] << endl;
while(hh <= tt)
{
int t = q[hh++];
for(int i = h[t];i != -1; i = ne[i])
{
int j = e[i];
if(st[j])
{
if(t1) cout <<"顶点 "<< j << " 的度数为 "<< d[j] << endl;
st[j] = 0;
q[++tt] = j;
}
}
}
memset(st,0,sizeof st);
}
/**************
函数名:Dft(int u,int v,string str,int len,int res )
输入:int u,int v,string str,int len,int res
功能:1/深度优先遍历
2/得到两节点全部简单路径
3/得到两节点长度为len的全部简单路径
输出:2/输出两节点全部简单路径
3/输出两节点长度为len的全部简单路径
**************/
void Dft(int u,int v,string str,int len,int res )
{
st[u] = 1;
if(u==v)
{
if(len==0)
{
for(int i = 0; i < str.size(); i ++)
{
if(i<str.size()-1)
cout << str[i] << "->";
else cout << str[i] <<endl;
}
}
else
{
if(res==len)
{
for(int i = 0; i < str.size(); i ++)
{
if(i<str.size()-1)
cout << str[i] << "->";
else cout << str[i] <<endl;
}
it = false;
}
}
}
for(int i = h[u]; i != -1; i = ne[i])
{
string ss = str;
int re = res;
int j = e[i];
res += data[i];
str+=j+48;
if(st[j])continue;
Dft(j,v,str,len,res);
res = re;
str = ss;
st[j] = 0;
}
}
/**************
函数名:Time_Complexity_Comparison()
输入:无
功能:比较深搜与宽搜
的时间复杂度
输出:输出比较结果
**************/
void Time_Complexity_Comparison()//比较两种遍历方法的时间复杂度
{
cout <<"用邻接矩阵存图,bfs算法的时间复杂度是:O(n^2)" <<endl;
cout <<"用邻接矩阵存图,dfs算法的时间复杂度是:O(n^2)" <<endl;
cout <<"用邻接表存图,bfs算法的时间复杂度是:O(n+e)" <<endl;
cout <<"用邻接表存图,dfs算法的时间复杂度是:O(n+e)" <<endl;
}
/**************
函数名:Get_Number_Of_Sides_Per_Point()
输入:无
功能:调用bft()函数的第二个功能
输出:输出每个节点的度数
**************/
void Get_Number_Of_Sides_Per_Point()//求顶点的度
{
Bft(1);
}
/**************
函数名:Judging_The_Existence_Of_Edges()
输入:无
功能:判断两个节点是否联通
输出:输出判断结果
**************/
void Judging_The_Existence_Of_Edges()//判断顶点u到v是否有边存在
{
int u,v;
cout <<"输入你想查询的边对应的顶点"<< endl;
cin >> u >> v;
if(g[u][v]!=0)cout <<"存在边"<<endl;
}
/**************
函数名:Determine_The_Simple_Path()
输入:无
功能:计算得到点u到v的所有的简单路径
输出:输出点u到v的所有的简单路径
**************/
void Determine_The_Simple_Path()//输出点u到v的所有的简单路径
{
int u,v;
cout <<"请输入两个点" <<endl;
cin >> u >> v;
string str ="";
str+=u+48;
memset(st,0,sizeof st);
Dft(u,v,str, 0,0);
}
/**************
函数名:Output_Simple_Path()
输入:无
功能:得到点u到v的所有长度
为length的所有的简单路径
输出:输出点u到v的所有长度
为length的所有的简单路径
**************/
void Output_Simple_Path()//输出点u到v的所有长度为length的所有的简单路径
{
int u,v,len;
cout <<"请输入两个顶点和一段长度" << endl;
cin >> u >> v >> len;
string str ="";
str+=u+48;
memset(st,0,sizeof st);
it = true;
Dft(u,v,str,len,0);
if(it) cout << "不存在该长度的路径" << endl;
}
/**************
函数名:Find_The_Shortest_Path()
输入:无
功能:求不带权的无向连通图
中顶点u到v的一条简单路径
输出:判断结果
**************/
void Find_The_Shortest_Path()//求不带权的无向连通图中顶点u到v的一条简单路径
{
int u;
int v;
cout <<"请输入两个顶点" << endl;
cin >> u >>v;
floyd();
if(dist[u][v]>= INF/2) cout << "这两点间不联通" << endl;
else cout <<"距离为:"<< dist[u][v] << endl;
}
/**************
函数名:Menu1()
输入:无
功能:完成各种输入
输出:无
**************/
void Menu1()
{
cout << "请输入顶点个数和边数"<<endl;
cin >> n >> m;
memset(h,-1,sizeof h);
memset(dist,0x3f,sizeof dist);
memset(g,0x3f,sizeof g);
for(int i = 1; i <= n ; i ++ )
for(int j = 1 ; j <= n ; j ++ )
if(i==j)
dist[i][j]=0;
for(int i = 0; i < m; i ++ )
{
cout << "请输入三个参数表示顶点a与顶点b以及它们之间的距离"<<endl;
int a,b,c;
cin >> a >> b >> c;
add(a,b,c);
g[a][b] = g[b][a] = min(c,g[a][b]);
dist[a][b] = dist[b][a] = 1;
d[b]++;
d[a]++;
}
system("pause");
system("cls");
}
/**************
函数名:Menu2()
输入:无
功能:消息循环函数
输出:无
**************/
void Menu2()
{
cout << "现在展示的是BFT" << endl;
Bft(0);
for(int i = 0; i < n ; i ++ )
{
if(i<n-1) cout <<q[i] << " ";
else cout << q[i] <<endl;
}
system("pause");
system("cls");
cout <<"因为DFT在后面的很多函数都有用到所有暂时不进行展示" << endl;
system("pause");
system("cls");
cout <<"现在展示的是判断顶点u到v是否有边存在" << endl;
Judging_The_Existence_Of_Edges();
system("pause");
system("cls");
cout <<"现在展示的是各个点的度数"<<endl;
Get_Number_Of_Sides_Per_Point();
system("pause");
system("cls");
cout <<"现在展示的输出两个点之间的所有简单路径"<< endl;
Determine_The_Simple_Path();
system("pause");
system("cls");
cout <<"现在展示的是输出两个点之间的长度为len 的所有的简单路径" << endl;
Output_Simple_Path();
system("pause");
system("cls");
cout << "现在展示的是任意两个顶点之间的最短距离,已经将全部边权设定为1" << endl;
Find_The_Shortest_Path();
system("pause");
system("cls");
}
int main()
{
Menu1();
Menu2();
return 0;
}