#include
#include
#include
#include
#include
#define MaxVertexNum 100 // 图中顶点数目的最大值
typedef int InfoType; // 边权信息
typedef int VertexType; // 顶点信息
typedef struct ArcNode{ // 边表结点
int adjvex; // 该弧指向的顶点的位置
struct ArcNode *next; // 指向下一条弧的指针
InfoType info; // 网的边权值
ArcNode(){ next = NULL; info = 0; };
ArcNode(int aj, InfoType io, ArcNode* p = NULL){ adjvex = aj; info = io; next = p; };
}ArcNode;
typedef struct VNode{ // 顶点表结点
VertexType data; // 顶点信息
ArcNode *first; // 指向第一条依附该顶点的弧的指针
VNode(){ first = NULL; data = 0; }
}VNode, AdjList[MaxVertexNum];
typedef struct{
AdjList vertices; // 邻接表
int vexnum, arcnum; // 图的顶点数和弧数
}ALGraph; // ALGraph是以邻接表存储的图的类型
测试数据1
5 7
1 2 1
1 5 1
2 5 1
5 4 1
2 3 1
2 4 1
3 4 1
测试数据2
7 6
1 2 1
1 3 1
2 6 1
2 5 1
3 4 1
3 7 1
// 通过输入信息创建一个 无向图
ALGraph creatGraph()
{
ALGraph gra;
int vn, an;
cout << "输入图的顶点数和边数:" << endl;
cin >> vn >> an;
gra.vexnum = vn;
gra.arcnum = an;
cout << "输入 x y z:表示 从顶点x到顶点y的权值是z:" << endl;
for (int i = 0, x, y, z; i < an; i++)
{
cin >> x >> y >> z;
ArcNode* p = gra.vertices[x].first;
gra.vertices[x].first = new ArcNode(y, z, p);
p = gra.vertices[y].first;
gra.vertices[y].first = new ArcNode(x, z, p);
}
return gra;
}
判断一个无向图G是不是一棵树,是返回True,否则返回false。
判断的话比较好判断:
不存在环的图就是一棵树。
是一个连通图并且图中边的个数比顶点个数少一个就是树。
对于判环操作,可以用并查集也可以用专门判断环的算法。相对而言第二种算法对于无向图的判断比较容易写代码,只需要遍历整个图记录下来图中的顶点和边信息即可判断。
// 判断图是不是一棵树辅助程序
void dfs(ALGraph &gra,int v, int *vis, int &vcnt, int &ecnt)
{
if (vis[v]){ return; }
vis[v] = 1;
vcnt++;
//cout << v << " ";
ArcNode *list = gra.vertices[v].first;
while (list)
{
ecnt++;
dfs(gra, list->adjvex, vis, vcnt, ecnt);
list = list->next;
}
return;
}
// 判断图是不是一棵树
bool isTree(ALGraph gra)
{
int vis[MaxVertexNum];
memset(vis, 0, sizeof(vis));
int ecnt = 0, vcnt = 0;
dfs(gra, 1, vis, vcnt, ecnt);
if (vcnt == gra.vexnum && ecnt == 2 * (gra.vexnum - 1))
return true;
return false;
}
写出图的DFS算法的非递归算法,图采用邻接表的形式存储。
DFS(深度搜索)采用栈。
BFS(广度搜索)采用队列。
// 深度搜索遍历整棵树
void dfsGraph(ALGraph gra)
{
if (gra.vexnum == 0) return;
stack<int> stk;
int vis[MaxVertexNum];
memset(vis, 0, sizeof(vis));
stk.push(1);
while (stk.size())
{
int nv = stk.top();
stk.pop();
if (vis[nv]) continue;
vis[nv] = 1;
cout << nv << endl; // 对节点进行访问操作
auto list = gra.vertices[nv].first;
while (list)
{
stk.push(list->adjvex);
list = list->next;
}
}
}
分别采用基于深度优先遍历和广度优先遍历算法判断以邻接表方式存储的图中是否存在由顶点vi到顶点vj的路径。
// 判断从a到b是否存在路径 深度优先
bool canAtoB_dfs(ALGraph gra, int a, int b)
{
if (a <= 0 || b <= 0 || a > gra.vexnum || b > gra.vexnum){
cerr << "输入的顶点不符合要求" << endl;
return false;
}
stack<int> stk;
stk.push(a);
int vis[MaxVertexNum];
memset(vis, 0, sizeof(vis));
while (stk.size())
{
int nv = stk.top();
stk.pop();
if (nv == b)return true;
if (vis[nv]) continue;
vis[nv] = 1;
auto list = gra.vertices[nv].first;
while (list)
{
stk.push(list->adjvex);
list = list->next;
}
}
return false;
}
// 判断从a到b是否存在路径 广度优先
bool canAtoB_bfs(ALGraph gra, int a, int b)
{
if (a <= 0 || b <= 0 || a > gra.vexnum || b > gra.vexnum)
{
cerr << "输入的顶点越界" << endl;
return false;
}
int vis[MaxVertexNum];
memset(vis, 0, sizeof(vis));
queue<int> que;
que.push(a);
while (que.size())
{
int nv = que.front();
que.pop();
if (nv == b) return true;
if (vis[nv]) continue;
vis[nv] = 1;
auto list = gra.vertices[nv].first;
while (list)
{
que.push(list->adjvex);
list = list->next;
}
}
return false;
}
输出所有从顶点Vi到顶点Vj的简单路径。
简单路径:序列中顶点不重复的路径。
// 打印图中所有从a到b的简单路径
// 简单路径:序列中顶点不重复的路径 深度搜索寻找路径
vector< vector<int> > dfs(ALGraph gra, int a, int b, vector<int> &path)
{
static vector<vector<int>> paths;
static int vis[MaxVertexNum] = { 0 };
//for (int i = 0; i < MaxVertexNum; i++)
// cout << vis[i] << " ";
//cout << endl;
//return vector>();
if (a <= 0 || a > gra.vexnum || b <= 0 || b > gra.vexnum) {
cerr << "输入的顶点格式不正确" << endl;
return vector<vector<int>>();
}
if (a == b){
path.push_back(b);
paths.push_back(path);
path.pop_back();
return vector<vector<int>>();
}
auto list = gra.vertices[a].first;
path.push_back(a);
vis[a] = 1;
while (list)
{
if(!vis[list->adjvex]) dfs(gra, list->adjvex, b, path);
list = list->next;
}
path.pop_back();
vis[a] = 0;
return paths;
}
// 打印所有从A到B的简单路径 辅助程序
void printPathsFromAtoB(ALGraph gra, int a, int b)
{
vector<int> path;
vector<vector<int>> paths;
paths = dfs(gra, a, b, path);
for (int i = 0; i < paths.size(); i++)
{
cout << "路径 " << i << " :";
for (int j = 0; j < paths[i].size(); j++)
{
cout << paths[i][j] << " ";
}
cout << endl;
}
}