【算法】图论(三) (20221030)

藏宝库编辑 2024-10-2 23:04:50 79 0 来自 中国
1. 图相干的算法

图中一个最常见的利用是,通过一个点遍历它的临边。
(1)毗邻矩阵:时间复杂度为O(V)。
(2)毗邻表:由于每一行原来存储的就是毗连的点,以是可以直接找到。
固然,以上利用将g这个图设置成public变量就可以实现,但是怎样维护g仍旧为private变量呢?由于,如许从筹划模式角度来讲是更好的,外界用户无法修改g这个图,固然可以利用一个函数,但是必要将数据复制一份,如许不是太好的,更好的方法呢?
利用迭代器
迭代器将详细实现隐藏了,如许希奇图和稠密图的接口就可以保持划一。
代码如下:
SparseGraph.h
#ifndef VERTEX_ADJACENT_ITERATOR_SPARSEGRAPH_H#define VERTEX_ADJACENT_ITERATOR_SPARSEGRAPH_H#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个空的vector, 表现每一个g都为空, 即没有任和边        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] == 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;        }        // 返回图G中与顶点v相毗连的下一个顶点        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();        }    };};#endif //VERTEX_ADJACENT_ITERATOR_SPARSEGRAPH_HDenseGraph.h
#ifndef VERTEX_ADJACENT_ITERATOR_DENSEGRAPH_H#define VERTEX_ADJACENT_ITERATOR_DENSEGRAPH_H#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[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){            assert( v >= 0 && v < G.n );            this->v = v;            this->index = -1;   // 索引从-1开始, 由于每次遍历都必要调用一次next()        }        ~adjIterator(){}        // 返回图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;            // 若没有顶点和v相毗连, 则返回-1            return -1;        }        // 检察是否已经迭代完了图G中与顶点v相毗连的全部顶点        bool end(){            return index >= G.V();        }    };};#endif //VERTEX_ADJACENT_ITERATOR_DENSEGRAPH_Hmain.cpp
#include <iostream>#include "SparseGraph.h"#include "DenseGraph.h"using namespace std;int main() {    int N = 20;    int M = 100;    srand( time(NULL) );    // Sparse Graph    SparseGraph g1(N , false);    for( int i = 0 ; i < M ; i ++ ){        int a = rand()%N;        int b = rand()%N;        g1.addEdge( a , b );    }    // O(E)    for( int v = 0 ; v < N ; v ++ ){        cout<<v<<" : ";        SparseGraph::adjIterator adj( g1 , v );        for( int w = adj.begin() ; !adj.end() ; w = adj.next() )            cout<<w<<" ";        cout<<endl;    }    cout<<endl;    // Dense Graph    DenseGraph g2(N , false);    for( int i = 0 ; i < M ; i ++ ){        int a = rand()%N;        int b = rand()%N;        g2.addEdge( a , b );    }    // O(V^2)    for( int v = 0 ; v < N ; v ++ ){        cout<<v<<" : ";        DenseGraph::adjIterator adj( g2 , v );        for( int w = adj.begin() ; !adj.end() ; w = adj.next() )            cout<<w<<" ";        cout<<endl;    }    return 0;}
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 16:44, Processed in 0.149120 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表