bosthhe1 / -

数据结构与算法(初阶)
0 stars 0 forks source link

图的基本概念以及实现 #29

Open bosthhe1 opened 1 year ago

bosthhe1 commented 1 year ago

图是由顶点集合和顶点间的关系组成的数据结构:G=(V,E),其中顶点集合V={x|x属于某个数据对象集合}是有穷非空集合 E={(X,Y)|X,Y属于V是顶点与顶点之间关系的有穷集合} (x,y)表示x到y的一条双通路,既(x,y)是无向图的一条边,Path(x,y)表示从x到y是单通路的,既路劲为 x->y 顶点和边:途中的节点称为顶点,第i个顶点基座vi。两个顶点的vi和vj相连叫做vi和vj之间存在一条边 在有向图,顶点对<x,y>是有序的,既<x,y>和<y,x>是不同的

完全图:在n个顶点的无向图中,若存在n(n-1)/2(这个是等差数列,第一个点和剩下n-1个点存在链接,第二个点和n-2个点存在链接,依次推导)条边,既任意两个顶点之间存在有且仅有一条边,则称为完全无向图。有向图中,若存在n(n-1)条边,则任意两个顶点之间存在有且仅有方向相反的边,称为完全有向图,这个完全有向图是最稠密的图

邻接顶点:在无向图中,若(x,y)是无向图的一两个顶点,且存在一条边,则x和y互称为邻接顶点,并称为边(x,y)依附于顶点x和顶点y,在有向图中,若x,y是有向图的两个顶点,且存在边<x,y>u,则称为x邻接到y,y邻接到自定点x,并称边u和顶点x和顶点y相关联

顶点的度:顶点x的度,是指和x相关联边的条数,记作deg(v),在有向图中顶点的度等于该顶点的入度和出度之和,在无向图中,顶底的度就是和顶点之间关联的边的条数

路径:从顶点vi触发有一组边使其可以达到顶点vj,则称为顶点vi到顶点vj的顶点序列为从顶点vi到顶点vj的路劲 路劲长度:对于不带权的图,路径长度就是指该路径上的边的条数,带权的图的路径是能到到目的地的权值的和

子图:若存在图G,另外存在图U,图U的顶点为G中存在的顶点,图U的边在G中存在的边,就像是sub_str()

连通图:在无向图中,若存在顶点v1到顶点v2存在路径,称v1到v2连通。若任意一对顶点之间都是连通的,则称为图为连通图。 强连通图:在有向图中,若存在每一对顶点v1和v2之间存在一条v1到v2的路径,也存在一条从v2到v1的路径,称为此图为强连通图

生成树:一个连通图的最小连通子图称作图的生成树,有n个顶点的连通图的生成树存在n个顶点和n-1条边,生成树中禁止存在环型结构 最小生成树:在生成树的基础上,存在总路劲之和最小

bosthhe1 commented 1 year ago
#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<vector>
#include<map>
#include<functional>
#include<queue>
using namespace std;

template<class T>
class UnioFindSet
{
public:
    UnioFindSet(const size_t& n)
    {
        v.resize(n, -1);
    }
    int FindRoot(size_t i)
    {
        int j = i;
        while (v[j] >= 0)
        {
            j = v[j];
        }
        int k = i;
        int next = v[k];
        while (next != v[j])
        {
            v[k] = j;
            k = next;
            next = v[k];
        }
        return j;
    }
    bool Union(size_t a,size_t b)
    {
        int i = FindRoot(a);
        int j = FindRoot(b);
        if (i!=j)
        {
            if (abs(v[i]) < abs(v[j]))
                swap(v[i], v[j]);
            v[i] += v[j];
            v[j] = i;
            return true;
        }
        return false;
    }
    bool Inset(size_t j,size_t k)
    {
        return FindRoot(j) == FindRoot(k); 
    }
public:
private:
    vector<T> v;
};
template<class W>
struct Edge
{
    size_t _dest;
    W _w;
    Edge<W>* next;
    Edge(size_t dest,const W& w)
        :_dest(dest)
        ,_w(w)
        ,next(nullptr)
    {}
};
template<class V, class W, W Max_w = INT_MAX, bool Direction = false>
class _Graph
{
    typedef Edge<W> Edge;
public:
    _Graph(const V* v, size_t n)//图的外面会给进来一个V类型数组,将数组中的每一个元素都分散开来,存在对应的下标
    {
        _vertexs.resize(n);
        for (int i = 0; i < n; i++)
        {
            _vertexs[i] = v[i];
            _IndexMap[v[i]] = i;
        }
        _table.resize(n, nullptr);
    }
    size_t GetVertexIndex(const V& v)
    {
        auto ret = _IndexMap.find(v);
        if (ret != _IndexMap.end())
        {
            return _IndexMap[v[i]];
        }
        return -1;
    }
    void AddEdge(const V& src, const V& dst, const W& w)
    {
        if (_IndexMap.find(src) != _IndexMap.end() &&
            _IndexMap.find(dst) != _IndexMap.end() &&
            _IndexMap.find(src) != _IndexMap.find(dst))
        {
            int srci = _IndexMap[src];
            int dsti = _IndexMap[dst];
            Edge* Ed = new Edge(dsti, w);
            Ed->next = _table[srci];
            _table[srci] = Ed;
            if (Direction == false)
            {
                Edge* Ed = new Edge(srci, w);
                Ed->next = _table[dsti];
                _table[dsti] = Ed;
            }
        }
    }
    void Print()
    {
        for (int i = 0; i < _table.size(); i++)
        {
            Edge* cur = _table[i];
            cout << "_table" << "[" << i << "] :";
            while (cur)
            {
                cout << "[" << cur->_dest << "]:"<<(_vertexs[cur->_dest].c_str())<<" ->";

                cur = cur->next;
            }
            cout << "nullptr" << endl;
            cout << endl;
        }
    }
private:
    vector<V> _vertexs;//顶点集合
    map<V, int> _IndexMap;//顶点和下标的映射关系
    vector<Edge*> _table;//出边表
};
template<class V,class W,W Max_w = INT_MAX,bool Direction = false>
class Graph
{
    typedef Graph<V, W, INT_MAX, Direction> Self;
public:
    Graph() = default;
    Graph(const V* v,size_t n)//图的外面会给进来一个v类型数组,将数组中的每一个元素都分散开来,存在对应的下标
    {
        _vertexs.resize(n);
        for (int i = 0; i < n; i++)
        {
            _vertexs[i] = v[i];
            _IndexMap[v[i]] = i;
        }
        _matrix.resize(n);
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                _matrix[i].push_back(INT_MAX);
            }
        }
    }
    size_t GetVertexIndex(const V& v)
    {
        auto ret = _IndexMap.find(v);
        if (ret != _IndexMap.end())
        {
            return _IndexMap[v[i]];
        }
        return -1;
    }
    void _AddEdge(size_t src, size_t dst, const W w)
    {
        _matrix[src][dst] = w;
        if (Direction == false)
            _matrix[src][dst] = w;
    }
    void AddEdge(const V& src, const V& dst, const W& w)
    {
        if (_IndexMap.find(src) != _IndexMap.end()&&
            _IndexMap.find(dst) != _IndexMap.end()&&
            _IndexMap.find(src) != _IndexMap.find(dst))
        {
            int j = _IndexMap[src];
            int k = _IndexMap[dst];
            _matrix[j][k] = w;
            if (Direction == false)
            _matrix[k][j] = w;
        }
    }
    void Print()
    {
        cout << "   ";
        for (int i = 0; i < _matrix.size(); i++)
        {
            cout << i << "    ";
        }
        cout << endl;
        for (int i = 0; i < _matrix.size(); i++)
        {
            cout << i << "  ";
            for (int j = 0; j < _matrix[i].size(); j++)
            {
                if (_matrix[i][j] == INT_MAX)
                {
                    cout << "*" << "    ";
                }
                else
                {
                    cout << _matrix[i][j] << "   ";
                }
            }
            cout << endl;
        }
    }
    void BFS(size_t n)
    {
        //自己想的,还不错
        //queue<vector<W>> q;
        //vector<bool> index(_vertexs.size(),false);
        //q.push(_matrix[n]);
        //int Count = 1;
        //index[n] = true;
        //cout << _vertexs[n].c_str() << endl;
        //while (!q.empty())
        //{
        //  vector<W> vw = (q.front());
        //  q.pop();
        //  Count--;
        //  for (int i = 0; i < vw.size(); i++)
        //  {
        //      if (vw[i] != INT_MAX&&index[i]==false)
        //      {
        //          cout << _vertexs[i].c_str()  << "[" << i << "]:" << " ";
        //          index[i] = true;
        //          q.push(_matrix[i]);
        //      }
        //  }
        //  if (Count == 0)
        //  {
        //      Count = q.size();
        //      cout << endl;
        //  }
        //}
        queue<int> q;
        vector<bool> index(_vertexs.size(), false);
        q.push(n);
        int Count = 1;
        size_t i = _vertexs.size();
        index[n] = true;
        cout << _vertexs[n].c_str() << endl;
        while (!q.empty())
        {
            while (Count--)
            {
                int src = q.front();
                q.pop();
                for (int j = 0; j < i; j++)
                {
                    if (_matrix[src][j] != INT_MAX&&index[j] == false)
                    {
                        cout << _vertexs[j].c_str() << "[" << j << "]:" << " ";
                        index[j] = true;
                        q.push(j);
                    }
                }
            }
            Count = q.size();
            cout << endl;
            if (q.empty())
            {
                for (int j = 0; j < n;j++)
                {
                    q.push(j);
                    break;
                }
            }
        }
    }
    void DFS(size_t i)
    {
        int n = _vertexs.size();
        vector<bool> index(n, false);
        index[i] = true;
        cout << _vertexs[i].c_str() << " ";
        _DFS(i,index);
    }
    struct Edge
    {
        size_t _src;
        size_t _dest;
        W _w;
        Edge(size_t src,size_t dest, const W& w)
            :_src(src)
            ,_dest(dest)
            , _w(w)
        {}
        bool operator>(const Edge& e2)const
        {
            return _w > e2._w;
        }
    };
    W Kruskal(Self& mintree)
    {
        priority_queue<Edge, vector<Edge>, greater<Edge>> pq;
        size_t n = _vertexs.size();
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (_matrix[i][j] != INT_MAX)
                {
                    Edge ed(i, j, _matrix[i][j]);
                    pq.push(ed);
                }
            }
        }
        W _w =W();
        vector<bool> v(n, false);
        UnioFindSet<int> ufs(n);
        while (!pq.empty())
        {
            Edge e = pq.top();
            pq.pop();
            if (ufs.Union(e._src, e._dest))
            {
                cout << e._src << "->" << e._dest << ":" << e._w << endl;
                mintree._AddEdge(e._src, e._dest, e._w);
                _w += e._w;
                n--;
            }
        }
        if (n == 1)
        {
            return _w;
        }
        return W();
    }
    private:
        void _DFS(size_t src, vector<bool>& index)
        {
            for (int i = 0; i < _vertexs.size();i++)
            {
                if (_matrix[src][i] != INT_MAX&&index[i] == false)
                {
                    cout << _vertexs[i].c_str() << " ";
                    index[i] = true;
                    _DFS(i, index);
                }
            }
            return;
        }
private:
    vector<V> _vertexs;//顶点集合
    map<V, int> _IndexMap;//顶点和下标的映射关系
    vector<vector<W>> _matrix;//顶点和顶点的权值关系
};