C++图论基础--图的两种表示实现及迭代

邻接矩阵存在的问题

如果我们的每一个顶点所连接的顶点只是周围的几个点, 那么形成的图是一个稀疏图,而我们生活中研究的大多数问题都是稀疏图问题, 比我我们研究的导航路径问题就是一个典型的稀疏图

邻接表

使用邻接矩阵方式实现一个稠密图

DenseGraph.cpp

#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
// 使用邻接矩阵方式实现一个稠密图
class DenseGraph{
private:
    int n, m;// 节点数和边数
    bool directed; // 是否为有向图
    vector<vector<bool>> g; // 图的具体数据
public:
    // 构造函数
    DenseGraph(int n, bool directed){
        assert(n >=0);
        this->n = n;
        this->m = 0;  // 初始化没有任何边
        this->directed = directed;
        // g初始化为n*n的布尔矩阵, 每一个g[i][j]均为false, 表示没有任和边
        g =  vector<vector<bool>>(n, vector<bool>(n, false));
    }
    ~DenseGraph(){};
    int V(){return n;}  // 返回节点个数
    int E(){return m;}  // 返回边的个数
    // 向图中添加一个边
    void addEdge(int v, int w){
        assert(v >=0 && v < n);
        assert(w >=0 && w < n);
        if (hasEdge(v, w))
            return;
        g[v][w] = true;
        if (!directed)
            g[w][v] = true;
        m++;
    }

    // 验证图中是否有从v到w的边
    bool hasEdge(int v, int w){
        assert(v >=0 && v < n);
        assert(w >=0 && w < n);
        return g[v][w];
    }
};
int main (){
     DenseGraph graph1(1, 1);
     DenseGraph graph2(3, 1);
    return 0;
}


使用邻接表方式实现一个稀疏图

#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
// 使用邻接表方式实现一个稀疏图
class SparseGraph{
private:
    int n, m;// 节点数和边数
    bool directed; // 是否为有向图
    vector<vector<int>> g; // 图的具体数据
public:
    // 构造函数
    SparseGraph(int n, bool directed){
        assert(n >=0);
        this->n = n;
        this->m = 0;  // 初始化没有任何边
        this->directed = directed;
        // g初始化为n*n的布尔矩阵, 每一个g[i][j]均为false, 表示没有任和边
        g =  vector<vector<int>>(n, vector<int>());
    }
    ~SparseGraph(){};
    int V(){return n;}  // 返回节点个数
    int E(){return m;}  // 返回边的个数
    // 向图中添加一个边
    void addEdge(int v, int w){
        assert(v >=0 && v < n);
        assert(w >=0 && w < n);
        g[v].push_back(w);
        if (v != w && !directed)
            g[w].push_back(v);
        m++;
    }

    // 验证图中是否有从v到w的边
    bool hasEdge(int v, int w){
        assert(v >=0 && v < n);
        assert(w >=0 && w < n);
        for (int i = 0; i < g[v].size(); i++) {
            if (g[v][i] == w)
                return true;
        }
        return false;
    }
};
int main (){
    SparseGraph graph1(1, 1);
    SparseGraph graph2(3, 1);
    return 0;
}

通过迭代器实现邻接表方式和邻接矩阵方式迭代(遍历)统一接口

vector的迭代器

#include <iostream>
#include <vector>
using namespace std;
int main (){
    // STL
    vector<int> v;
    for (int i = 0; i < 5; i++) {
        v.push_back(i);
    }
    // 1 遍历;
    for (int i = 0; i < v.size(); i++) {
        cout<< v[i] <<", ";
    }
    cout <<endl;
    // 2 迭代器
    for (vector<int>::iterator it = v.begin(); it != v.end() ;it++) {
        cout<< *it <<endl;
    }
    return 0;
}

邻接表的方式实现迭代并测试

#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
// 使用邻接表方式实现一个稀疏图
class SparseGraph{
private:
    int n, m;// 节点数和边数
    bool directed; // 是否为有向图
    vector<vector<int>> g; // 图的具体数据
public:
    // 构造函数
    SparseGraph(int n, bool directed){
        assert(n >=0);
        this->n = n;
        this->m = 0;  // 初始化没有任何边
        this->directed = directed;
        // g初始化为n*n的布尔矩阵, 每一个g[i][j]均为false, 表示没有任和边
        g =  vector<vector<int>>(n, vector<int>());
    }
    ~SparseGraph(){};
    int V(){return n;}  // 返回节点个数
    int E(){return m;}  // 返回边的个数
    // 向图中添加一个边
    void addEdge(int v, int w){
        assert(v >=0 && v < n);
        assert(w >=0 && w < n);
        if (hasEdge(v, w))
            return;
        g[v].push_back(w);
        if (v != w && !directed)
            g[w].push_back(v);
        m++;
    }

    // 验证图中是否有从v到w的边
    bool hasEdge(int v, int w){
        assert(v >=0 && v < n);
        assert(w >=0 && w < n);
        for (int i = 0; i < g[v].size(); i++) {
            if (g[v][i] == w)
                return true;
        }
        return false;
    }

    // 邻边迭代器, 传入一个图和一个顶点,
    // 迭代在这个图中和这个顶点向连的所有顶点
    class adjIterator{
    private:
        SparseGraph &G; // 图G的引用
        int v; // 顶点数
        int index; // 表示索引
    public:
        // 构造函数
        adjIterator(SparseGraph &graph, int v): G(graph){
            this->v = v;
            this->index = 0;
        }
        ~adjIterator(){}
        // 返回图G中与顶点v相连接的第一个顶点
        int begin(){
            index = 0;
            if (G.g[v].size())
                return  G.g[v][index];
            // 若没有顶点和v相连接, 则返回-1
            return -1;
        }
        int next(){
            index++;
            if (index < G.g[v].size())
                return  G.g[v][index];
            // 若没有顶点和v相连接, 则返回-1
            return -1;
        }
        //查看是否已经迭代完了图G中与顶点v相连接的所有顶点
        bool end(){
            return index >= G.g[v].size();
        }
    };
};
int main (){
    int N = 20, M = 100;  // 20个顶点 100个边
    SparseGraph graph(N, false);
    for (int i = 0; i < M; i++) {
        int a = rand()%N;
        int b = rand()%N;
        graph.addEdge(a, b);
    }
    // 遍历
    for (int v = 0; v < N; v++) {
        cout<< v << " : ";
        SparseGraph::adjIterator adj(graph, v);
        for (int w = adj.begin(); !adj.end(); w = adj.next()) {
            cout<< w <<" ";
        }
        cout<<endl;

    }
    return 0;
}

在这里插入图片描述

邻接矩阵的方式实现迭代并测试


#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
// 使用邻接矩阵方式实现一个稠密图
class DenseGraph{
private:
    int n, m;// 节点数和边数
    bool directed; // 是否为有向图
    vector<vector<bool>> g; // 图的具体数据
public:
    // 构造函数
    DenseGraph(int n, bool directed){
        assert(n >=0);
        this->n = n;
        this->m = 0;  // 初始化没有任何边
        this->directed = directed;
        // g初始化为n*n的布尔矩阵, 每一个g[i][j]均为false, 表示没有任和边
        g =  vector<vector<bool>>(n, vector<bool>(n, false));
    }
    ~DenseGraph(){};
    int V(){return n;}  // 返回节点个数
    int E(){return m;}  // 返回边的个数
    // 向图中添加一个边
    void addEdge(int v, int w){
        assert(v >=0 && v < n);
        assert(w >=0 && w < n);
        if (hasEdge(v, w))
            return;
        g[v][w] = true;
        if (!directed)
            g[w][v] = true;
        m++;
    }

    // 验证图中是否有从v到w的边
    bool hasEdge(int v, int w){
        assert(v >=0 && v < n);
        assert(w >=0 && w < n);
        return g[v][w];
    }

    // 邻边迭代器, 传入一个图和一个顶点,
    // 迭代在这个图中和这个顶点向连的所有顶点
    class adjIterator{
    private:
        DenseGraph &G; // 图G的引用
        int v; // 顶点数
        int index; // 表示索引
    public:
        // 构造函数
        adjIterator(DenseGraph &graph, int v): G(graph){
            this->v = v;
            this->index = -1;
        }
        // 返回图G中与顶点v相连接的第一个顶点
        int begin(){
            // 索引从-1开始, 因为每次遍历都需要调用一次next()
            index = -1;
            return next();
        }
        // 返回图G中与顶点v相连接的下一个顶点
        int next(){
            // 从当前index开始向后搜索, 直到找到一个g[v][index]为true
            for (index += 1; index < G.V(); index++) {
                if (G.g[v][index])
                    return index;
            }
            return -1;
        }
        //查看是否已经迭代完了图G中与顶点v相连接的所有顶点
        bool end(){
            return index >= G.V();
        }
    };
};
int main (){
    int N = 20, M = 100;  // 20个顶点 100个边
    DenseGraph graph(N, false);
    for (int i = 0; i < M; i++) {
        int a = rand()%N;
        int b = rand()%N;
        graph.addEdge(a, b);
    }
    // 遍历  On^2
    for (int v = 0; v < N; v++) {
        cout<< v << " : ";
        DenseGraph::adjIterator adj(graph, v);
        for (int w = adj.begin(); !adj.end(); w = adj.next()) {
            cout<< w <<" ";
        }
        cout<<endl;

    }

    return 0;
}

在这里插入图片描述

我们可以看出邻接矩阵迭代的时间赋值读为On^2 而 邻接表为 On

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值