一、邻接表的简单实现:
#include <list>
#include <vector>
using namespace std;
class Graph {
public:
int numVertices;
list<int> *adjLists;
public:
Graph(int vertices) : numVertices(vertices), adjLists(new list<int>[vertices]) {}
~Graph() {
delete[] adjLists;
}
void addEdge(int vertex1, int vertex2, bool isDirected = true) {
adjLists[vertex1].push_back(vertex2);
if (!isDirected) {
adjLists[vertex2].push_back(vertex1);
}
}
};
二、图的两种遍历方式
1.深度优先遍历
void DFS(Graph &graph, int vertex) {
vector<bool> visited(numVertices, false);
stack<int> stack;
visited[vertex] = true;
stack.push(vertex);
while (!stack.empty()) {
int current = stack.top();
stack.pop();
cout << current << " ";
for (int adjVertex : graph.adjLists[current]) {
if (!visited[adjVertex]) {
visited[adjVertex] = true;
stack.push(adjVertex);
}
}
}
}
2.广度优先遍历
void BFS(Graph &graph, int startVertex) {
vector<bool> visited(numVertices, false);
queue<int> queue;
visited[startVertex] = true;
queue.push(startVertex);
while (!queue.empty()) {
int current = queue.front();
queue.pop();
cout << current << " ";
for (int adjVertex : graph.adjLists[current]) {
if (!visited[adjVertex]) {
visited[adjVertex] = true;
queue.push(adjVertex);
}
}
}
}
三、有向图找环
使用深度遍历算法的基础上,额外增加path和history数组,path表示已遍历的路径,history表示某一个点是否位于路径上;当某一个点位于路径上则构成环,通过path向前查找起点(起点和终点相同),输出环;找到一个环后,要回溯history和path到上一个分叉处,stack的栈顶的元素即代表下一个分叉处。
如图:已遍历0 - 1 - 2 - 7 - 8,下一个点为0为路径中的点,则找到环,此时回溯,将8 、7从路径中删除,下一个点从3开始遍历
注意:此算法找到的不一定是最小的环
#include<stack>
#include<vector>
#include<iostream>
#include <Graph.hpp>
void DFS(std::list<int>* adjLists, int size, int start, std::vector<bool>& visited) {
std::vector<bool> path(size, false);
std::vector<int> history;
std::stack<std::pair<int,int>> stack;
stack.push({start, -1});
visited[start] = true;
while (!stack.empty()) {
int current = stack.top().first;
stack.pop();
path[current] = true;
history.push_back(current);
for (int adjVertex : adjLists[current]) {
if (!visited[adjVertex]) {
visited[adjVertex] = true;
stack.push({adjVertex, current});
} else {
if(path[adjVertex]){
std::cout << " find: " << std::endl;
std::cout << adjVertex << std::endl;
if(!history.empty()){
for(int s = history.size() - 1; history[s] != adjVertex;--s){
std::cout << history[s] << std::endl;
}
}
if(!stack.empty()){
for(int s = history.size() - 1;history[s] != stack.top().second;--s){
path[history[s]] = false;
history.pop_back();
}
}
}
}
}
}
}
int main(int argc, char *argv[]){
myGraph::Graph graph(14);
graph.addEdge(0,1);
graph.addEdge(1,2);
graph.addEdge(2,3);
graph.addEdge(3,6);
graph.addEdge(6,5);
graph.addEdge(5,4);
graph.addEdge(4,2);
graph.addEdge(2,7);
graph.addEdge(7,8);
graph.addEdge(8,0);
graph.addEdge(9,10);
graph.addEdge(10,11);
graph.addEdge(12,13);
graph.addEdge(13,8);
std::vector<bool> visited(graph.numVertices, false);
for (int i = 0; i < graph.numVertices; ++i) {
if(visited[i])
continue;
DFS(graph.adjLists,graph.numVertices, i, visited);
}
return 0;
}
输出结果:
find:
0
8
7
2
1
find:
2
4
5
6
3
参考链接 数据结构篇-图(Graph)