有向图、无向图邻接表(Adjacency List)的简单实现(C++ Graph)

一、邻接表的简单实现: 

#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)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++编程创建无向图邻接表有向图邻接表和逆邻接表的示例代码: 1. 创建无向图邻接表: ```cpp #include <iostream> #include <list> using namespace std; class Graph { int V; list<int> *adj; public: Graph(int V) { this->V = V; adj = new list<int>[V]; } void addEdge(int v, int w) { adj[v].push_back(w); adj[w].push_back(v); } void printAdjList() { for (int v = 0; v < V; ++v) { cout << "Adjacency list of vertex " << v << ": "; for (auto it = adj[v].begin(); it != adj[v].end(); ++it) cout << *it << " "; cout << endl; } } }; int main() { int V = 5; Graph g(V); g.addEdge(0, 1); g.addEdge(0, 4); g.addEdge(1, 2); g.addEdge(1, 3); g.addEdge(1, 4); g.addEdge(2, 3); g.addEdge(3, 4); g.printAdjList(); return 0; } ``` 2. 创建有向图邻接表和逆邻接表: ```cpp #include <iostream> #include <list> using namespace std; class Graph { int V; list<int> *adj; list<int> *revAdj; public: Graph(int V) { this->V = V; adj = new list<int>[V]; revAdj = new list<int>[V]; } void addEdge(int v, int w) { adj[v].push_back(w); revAdj[w].push_back(v); } void printAdjList() { cout << "Adjacency list:" << endl; for (int v = 0; v < V; ++v) { cout << "Vertex " << v << ": "; for (auto it = adj[v].begin(); it != adj[v].end(); ++it) cout << *it << " "; cout << endl; } cout << endl; cout << "Reverse adjacency list:" << endl; for (int v = 0; v < V; ++v) { cout << "Vertex " << v << ": "; for (auto it = revAdj[v].begin(); it != revAdj[v].end(); ++it) cout << *it << " "; cout << endl; } } }; int main() { int V = 5; Graph g(V); g.addEdge(0, 1); g.addEdge(0, 4); g.addEdge(1, 2); g.addEdge(1, 3); g.addEdge(2, 3); g.addEdge(3, 4); g.printAdjList(); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值