说在前面
无向图
-
相关概念
以下图为例
- 邻接矩阵
无向图,只要一半就行
顶点0与顶点1之间存在边,则在矩阵[0][1]位置填上1;酱紫
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191006112508337.png#pic_center?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNDQ2MTAw,size_16,color_FFFFFF,t_70)
- 邻接表
与顶点0相连的顶点有顶点4与顶点1,那么将这两点的数据填入0后的链表;酱紫
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019100611540912.png#pic_center?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNDQ2MTAw,size_16,color_FFFFFF,t_70)
-
图的表示
在以下实现中使用了STL容器(vector、queue、stack等)以及智能指针(shared_ptr),相关概念自行了解。
在该示例中,图的存储使用邻接表。
struct ArcNode
{
int adjvex;
shared_ptr<ArcNode> nextarc;
};
struct VNode
{
int val;
int color;
shared_ptr<ArcNode> firstarc;
};
enum Color
{
black,
white
};
class MGraph
{
private:
int vernum;
int arcnum;
vector<VNode> vertices;
public:
MGraph(vector<vector<int>>);
void BFS(int s);
void DFS(int s);
void DFSRecursive();
void DFSRecursive_Visit(int s);
void setWhite();
};
-
构造
使用邻接矩阵来进行初始化MGraph::MGraph(vector<vector<int>> arr)
{
vernum = arr.size();
vertices.resize(vernum);
for (int i = 0; i < vernum; i++)
{
vertices[i].firstarc = nullptr;
vertices[i].color = white;
vertices[i].val = i;
for (int j = i; j < vernum; j++)
{
if (arr[i][j])
{
arcnum++;
shared_ptr<ArcNode> p = make_shared<ArcNode>();
p->adjvex = j;
p->nextarc = vertices[i].firstarc;
vertices[i].firstarc = p;
}
}
}
}
-
广度优先遍历
(这是个gif)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191006144751652.gif)
void MGraph::BFS(int s)
{
queue<VNode> que;
vertices[s].color = black;
que.push(vertices[s]);
while (!que.empty())
{
VNode temp = que.front();
que.pop();
cout << temp.val << endl;
shared_ptr<ArcNode> p = temp.firstarc;
while (p)
{
if (vertices[p->adjvex].color == white)
{
vertices[p->adjvex].color = black;
que.push(vertices[p->adjvex]);
}
p = p->nextarc;
}
}
}
-
深度优先遍历-递归
递归的比较简单,就不画图了 (好难画啊)
void MGraph::DFSRecursive()
{
for (int i = 0; i < vernum; i++)
if (vertices[i].color == white)
DFSRecursive_Visit(i);
}
void MGraph::DFSRecursive_Visit(int s)
{
vertices[s].color = black;
cout << vertices[s].val << endl;
shared_ptr<ArcNode> p = vertices[s].firstarc;
while (p)
{
if (vertices[p->adjvex].color == white)
DFSRecursive_Visit(p->adjvex);
p = p->nextarc;
}
}
-
深度优先遍历-非递归
非递归遍历使用到了栈,但是与广度优先遍历时使用到的队列有一些不同,在入栈操作时仅需要将第一个未访问的节点入栈,注意其中的break
(这是个gif)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191006153944277.gif)
void MGraph::DFS(int s)
{
for (int i = 0; i < vernum; i++)
{
if (vertices[i].color == white)
{
stack<VNode> mstack;
vertices[s].color = black;
mstack.push(vertices[s]);
while (!mstack.empty())
{
cout << mstack.top().val << endl;
VNode temp = mstack.top();
mstack.pop();
shared_ptr<ArcNode> p = temp.firstarc;
while (p)
{
if (vertices[p->adjvex].color == white)
{
vertices[p->adjvex].color = black;
mstack.push(vertices[p->adjvex]);
break;
}
p = p->nextarc;
}
}
}
}
}
Code
#include <iostream>
#include <stack>
#include <queue>
#include <memory>
#include <unordered_map>
using namespace std;
struct ArcNode
{
int adjvex;
shared_ptr<ArcNode> nextarc;
};
struct VNode
{
int val;
int color;
shared_ptr<ArcNode> firstarc;
};
enum Color
{
black,
white
};
class MGraph
{
private:
int vernum;
int arcnum;
vector<VNode> vertices;
public:
MGraph(vector<vector<int>>);
void BFS(int s);
void DFS();
void DFSRecursive();
void DFSRecursive_Visit(int s);
void setWhite();
};
MGraph::MGraph(vector<vector<int>> arr)
{
vernum = arr.size();
vertices.resize(vernum);
for (int i = 0; i < vernum; i++)
{
vertices[i].firstarc = nullptr;
vertices[i].color = white;
vertices[i].val = i;
for (int j = i; j < vernum; j++)
{
if (arr[i][j])
{
arcnum++;
shared_ptr<ArcNode> p = make_shared<ArcNode>();
p->adjvex = j;
p->nextarc = vertices[i].firstarc;
vertices[i].firstarc = p;
}
}
}
}
void MGraph::BFS(int s)
{
queue<VNode> que;
vertices[s].color = black;
que.push(vertices[s]);
while (!que.empty())
{
VNode temp = que.front();
que.pop();
cout << temp.val << endl;
shared_ptr<ArcNode> p = temp.firstarc;
while (p)
{
if (vertices[p->adjvex].color == white)
{
vertices[p->adjvex].color = black;
que.push(vertices[p->adjvex]);
}
p = p->nextarc;
}
}
}
void MGraph::DFS()
{
for (int i = 0; i < vernum; i++)
{
if (vertices[i].color == white)
{
stack<VNode> mstack;
vertices[i].color = black;
mstack.push(vertices[i]);
while (!mstack.empty())
{
cout << mstack.top().val << endl;
VNode temp = mstack.top();
mstack.pop();
shared_ptr<ArcNode> p = temp.firstarc;
while (p)
{
if (vertices[p->adjvex].color == white)
{
vertices[p->adjvex].color = black;
mstack.push(vertices[p->adjvex]);
break;
}
p = p->nextarc;
}
}
}
}
}
void MGraph::DFSRecursive()
{
for (int i = 0; i < vernum; i++)
if (vertices[i].color == white)
DFSRecursive_Visit(i);
}
void MGraph::DFSRecursive_Visit(int s)
{
vertices[s].color = black;
cout << vertices[s].val << endl;
shared_ptr<ArcNode> p = vertices[s].firstarc;
while (p)
{
if (vertices[p->adjvex].color == white)
DFSRecursive_Visit(p->adjvex);
p = p->nextarc;
}
}
void MGraph::setWhite()
{
for (int i = 0; i < vernum; i++)
vertices[i].color = white;
}
int main()
{
vector<vector<int>> arr(5, vector<int>(5, 0));
cout << "BFS:" << endl;
arr[0][1] = 1; arr[0][4] = 1;
arr[1][2] = 1; arr[1][3] = 1; arr[1][4] = 1;
arr[2][3] = 1;
arr[3][4] = 1;
MGraph m(arr);
m.BFS(0);
cout << "DFS(测试用例不同):"<<endl;
arr[0][1] = 1; arr[0][4] = 1;
arr[1][2] = 1; arr[1][3] = 1; arr[1][4] = 0;
arr[2][3] = 0;
arr[3][4] = 1;
m.setWhite();
m.DFS();
return 0;
}