【数据结构】:图

来源:互联网 发布:宽带网络套餐十机顶盒 编辑:程序博客网 时间:2024/06/14 10:45

  • 1、定义是一种非线性结构,由顶点的集合和顶点间的关系的集合组成的一种数据结构。
    Graph = (V,E);
    V = {x|x是顶点的集合};
    E = {<x,y> |(x,y属于V)};
  • 2、图的分类有向图:顶点之间单向指引就是有向图无向图:顶点之间可以互相指引就是无向图
    这里写图片描述
  • 3、一些基本概念
    1)完全图:在由n个顶点组成的无向图中,若有n(n-1)/2条边,则就是完全无向图
    2)权重:在一些图中,边具有与之相关的数值,称为权重。
    3)邻接顶点:如果(u,v)是图中的一条边,那么u,v互为邻接点。
    4)度:与顶点相关联的边的数目
    5)路径:一个顶点到另一个顶点所经过的痕迹
    6)连通图:在无向图中,任意两个顶点之间都是连通的。
    7)强连通图:在有向图中,若每一对顶点之间都存在路径,就称此图为强连通图。
    8)生成树:若一个图有n个顶点,则有n-1条边的就是生成树
    一个无向连通图的生成树是它的极小连通子图。
    -4、图的存储方法
    1)邻接矩阵
    A:如何存储:
    这里写图片描述
    B:代码如何实现:
template<class V,class W>class GraphMatrix{public:    //构造函数    GraphMatrix(V* v,size_t n,bool isDirected = false,const W& invalue = W())        :_v(v,v+n)        ,_isDirected(isDirected)    {        _matrix = new W*[_v.size()];        for(size_t i = 0; i<n; i++)        {            _matrix[i] = new W[_v.size()];            for(size_t j = 0; j<n; j++)            {                _matrix[i][j] = invalue;            }        }    }    //给定一个顶点,如何得到这个顶点的下标    size_t GetIndex(const V& v)    {        for(size_t i = 0; i<_v.size(); i++)        {            if(_v[i] == v)            {                return i;            }        }        assert(false);        return 0;    }    //如何加一条边    void AddEge(const V& v1, const V& v2, const W& w)    {        size_t src = GetIndex(v1);        size_t dest = GetIndex(v2);        _matrix[src][dest] = w;        if(_isDirected = false) //说明是无向图        {            _matrix[dest][src] = w;        }    }    //析构函数    ~GraphMatrix()    {        //先释放数据        for(size_t i = 0; i<_v.size(); i++)        {            delete[] _matrix[i];        }        //后释放指针数组        delete[] _matrix;    }private:    vector<V> _v;     //顶点的集合    W** _matrix;       //边上权重的集合    bool _isDirected;  //是否是与有向图};

2)邻接表
A:如何存储:
这里写图片描述
节点的设置:

template<class W>struct GraphLinkNode{    W _weight;       //权重    GraphLinkNode<W*> _next;  //下一个节点    size_t _src;          size_t _dest;    GraphLinkNode(size_t src,size_t dest,const W& weight = W())        :_weight(weight)        ,_next(NULL)        ,_src(src)        ,_dest(dest)    {}};

B:代码如何实现

template<class V, class W>class GraphLink{    typedef LinKEdge<W> Edge;public:    GraphLink(V* vertexs, size_t n, const W& invalid = W(), bool isDirected = false)        :_isDirected(isDirected)    {        _vertexs.resize(n);        _vertexs.assign(vertexs, vertexs+n);        _linkTables.resize(n, NULL);    }    size_t GetVertexIndex(const V& v)    {        for (size_t i = 0; i < _vertexs.size(); ++i)        {            if (_vertexs[i] == v)            {                return i;            }        }        assert(false);        return 0;    }    void _AddEdge(size_t src, size_t dst, const W& w)    {        // 头插        LinKEdge<W>* edge = new Edge(src, dst, w);        edge->_next = _linkTables[src];        _linkTables[src] = edge;    }    void AddEdge(const V& v1, const V& v2, const W& w)    {        size_t src = GetVertexIndex(v1);        size_t dst = GetVertexIndex(v2);        _AddEdge(src, dst, w);        if (_isDirected == false)        {            _AddEdge(dst, src, w);        }    }protected:    vector<V> _vertexs;  // 顶点集合    vector<Edge*> _linkTables; // 邻接表    bool _isDirected;};

邻接矩阵和邻接表的比较及各自的用途:
说明:
A:就定义来说:
邻接矩阵更适合直接定位
邻接表适合搜寻相邻节点
B:存储
邻接矩阵:在无向图的存储中,邻接矩阵的存储方式是一种对称矩阵,这样的存储方式可以节省很大的内存空间
邻接表:在无向图的存储中,是要将重复的元素再次进行存储的,因此会有空间上的开销
C:找寻元素的相邻边
邻接矩阵:要按行,列,依次进行查找,时间复杂度很高
邻接表:直接就遍历依次指向此节点的链表即可
- 5、图的遍历
1)分类:
深度优先遍历
广度优先遍历
这里写图片描述
2)代码如何实现
A:深度优先遍历

void DFS(const V& src)    {        size_t index = GetVertexIndex(src);        vector<bool> visited(_vertexs.size(),false);        visited[index] = true;        cout<<_vertexs[index]<<"->";        _DFS(index,visited);    }    void _DFS(size_t src,vector<bool>& visited)    {        Edge* cur = _linkTables[src];        while(cur)        {            size_t dst = cur->_dst;            if(visited[dst] == false)            {                cout<<_vertexs[dst]<<"->"<<" ";                visited[dst] = true;                _DFS(dst,visited);            }            cur = cur->_next;        }    }

B:广度优先遍历

void BFS(const V& src)    {        size_t index = GetVertexIndex(src);        vector<bool> visited(_vertexs.size(),false);        queue<int> q;        q.push(index);        while(!q.empty())        {            size_t front = q.front();            if(visited[front] == false)            {                cout<<_vertexs[front]<<"->";                visited[front] = true;                Edge* cur = _linkTables[front];                while(cur)                {                    size_t dst = cur->_dst;                    if(visited[dst] == false)                    {                        q.push(dst);                        visited[dst] = true;                        cout<<_vertexs[dst]<<"->";                    }                    cur = cur->_next;                }            }            q.pop();        }    }
0 0
原创粉丝点击