• 探索邻接表


    网上看到过很多版本是用链表实现的,可能这样比较安全吧。个人总感觉用指针指来指去的代码比较丑= =

    所以我想试试看用STL给的模版实现一下,可能安全性不够,之后学精了后再作修改吧。

    于是便在此记录代码的成长。

    代码的功能是可以实现创建一个图结构、计算这个图的出度和入度、进行深搜和广搜、打印图。

    图的结点是以“0”作为起点,当然这个“0”可能用不上,但万一用上了又没有岂不是尴尬~

    结点的权值默认是int类型,这并不完善,之后我会改写成函数模版的形式。

    为什么会想到用vector<list<T> >?

    vector[ i ]  这个“ i ” 就可以表示每个顶点,接着vector[ i ] 里面的内容是 list<T> ,而这个list就可以表示每个顶点所属的边表。

    举个栗子: 以3为顶点的边表是这样的: 3: 1 -> 5 -> 8   这时候,list 里面没有“3”这个元素,但要访问完整的边表的话,“3” 应该也是要被检查一下是否访问过。

    怎么办呢? 这时候vector[ i ] 里面的“ i ” 就可以充当成这个“ 3 ”,也就是说我们在进行DFS或BFS的时候可以先 visited[ i ],这就达到了检查“3”——也就是边表的

    顶点有没有被访问过的目的了。

    .h代码如下:

    #ifndef AC
    #define AC 
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<list>
    using namespace std;
    const int MAXL=1000;
    bool visited[MAXL];  //visited数组用来标记某点是否被访问过
    int n, m;            //n,m 分别表示待输入的顶点数和边数
    
    class Graph_AD
    {
        public:
            Graph_AD(int Vnum, int Enum);
            bool check_edge_value(int, int);
            void getIOdegree();
            void creatGraph();
            void showGraph();
            void showIOdegree();
            void DFS();     //进行深搜
            void dfs(int);
            void BFS();     //进行广搜
            void bfs(int);
        private:
            int vertax;     //顶点数
            int edge;       //边数
            vector<pair<int, int> > In_Out_degree;  //用来记录每个顶点出入度的数组  first表示入度  second表示出度   
            vector< list<int> > map;
    };
    
    #endif 

    .cpp文件如下:

    #include"Graph_by_Adjacency_list.h" 
    
    Graph_AD::Graph_AD(int Vnum, int Enum): vertax(Vnum), edge(Enum) { };
    
    bool Graph_AD::check_edge_value(int start, int end)    //检查输入是否正确,如果结点大于或者小于规定的边界就越界了,你是想搞事情吗?? 
    {
            if (start<0 || end<0 || start>vertax || end>vertax) 
            return false;
        return true;
    }
    
    void Graph_AD::getIOdegree()
    {
        In_Out_degree.resize(vertax+1);
        for (int i=0; i<=vertax; ++i)
        {
            if (!map[i].empty())   //这里要注意,当map[i]有元素时,也就是该顶点的边表不为空时才能计算出度和入度 
            {
                list<int>::iterator it;
                for (it=map[i].begin(); it!=map[i].end(); ++it)
                {
                 ++In_Out_degree[i].second;
                 ++In_Out_degree[*it].first;
                }
            }
        }
    }
    
    void Graph_AD::creatGraph()
    {
        map.resize(vertax+1);
        cout << "请输入" << edge << "条边" << endl; 
        for (int i=0; i<edge; ++i)  
        {
            int start, end;
            cin >> start >> end;
            while (!check_edge_value(start, end))
            {
                cout << "输入有误,请重新输入" << endl;
                cin >> start >> end;
            }
            map[start].push_back(end);
        }
    }
    
    void Graph_AD::showGraph()
    {
        cout << "图的邻接表如下:" << endl;
        for (int i=0; i<=vertax; ++i)
        {
            if (!map[i].empty())
            {
                cout << "Vertax " << i << ": ";
                list<int>::iterator it;
                for (it=map[i].begin(); it!=map[i].end(); ++it)
                {
                    cout << *it <<"->";
                }
                cout << "^" << endl;
            }
        }
    }
    
    void Graph_AD::showIOdegree()
    {
        for (int i=0; i<=vertax; ++i)
        {
            cout << "Vertax " << i << "-> Id: " << In_Out_degree[i].first << endl 
            <<"        Od: " <<In_Out_degree[i].second << endl;
        }
    }
    
    bool check(int Vexnum, int edge)   //检查输入的顶点数和边数合不合法, 顶点数和边数的关系是:((Vexnum*(Vexnum - 1)) / 2) < edge
    {
        if (Vexnum<=0 || edge<=0 || ((Vexnum*(Vexnum-1))/2)<edge)
            return false;
        return true;
    }
    
    void Graph_AD::DFS()
    {
        cout << "深搜结果为:" << endl; 
        memset(visited, true, sizeof(visited));
        for (int i=0; i<=vertax; ++i)
        {
            if (!map[i].empty() && visited[i]==true)  //此处检查是否访问需满足两个条件: map[i]有元素,且i这个顶点未被访问过
            {
                cout << i << " ";    //此处就是开头提到的先访问顶点的问题,用 i 来访问顶点 
                visited[i]=false;    
                dfs(i);
            }
        }
        cout << endl;
    }
    
    void Graph_AD::dfs(int now)
    {
        list<int>::iterator it;
        for (it=map[now].begin(); it!=map[now].end(); ++it)
        {
            if (visited[*it]==true)
            {
                cout << *it << " ";
                visited[*it]=false;
                dfs(*it);
            }
        }
    }
    
    void Graph_AD::BFS()
    {
        cout << "广搜结果为:" << endl; 
        memset(visited, true, sizeof(visited));
        for (int i=0; i<=vertax; ++i)
        {
            if (!map[i].empty() && visited[i]==true)   //此处同理DFS情形 
            {
                cout << i << " ";    //此处同理DFS情形 
                visited[i]=false;
                bfs(i);
            }
        }
        cout << endl;
    }
    
    void Graph_AD::bfs(int now)
    {
        list<int>::iterator it;
        queue<int> q;
        q.push(now);
        while (!q.empty())
        {
            now=q.front();
            q.pop();
            for (it=map[now].begin(); it!=map[now].end(); ++it)
            {
                if (visited[*it]==true)
                {
                    cout << *it << " ";
                    visited[*it]=false;
                }
            }
        }
        cout << endl;
    }

    main.cpp文件如下:

    #include"Graph_by_Adjacency_list.cpp" 
    
    int main()
    {
        cout << "输入图的顶点个数和边的条数:" << endl;
        cin >> n >> m;
        while (!check(n, m))
        {
            cout << "输入的数值不合法,请重新输入" << endl;
            cin >> n >> m;
        }
        Graph_AD g1(n, m);
        g1.creatGraph();
        g1.showGraph();
        cout << "-------------------------------" << endl;
        g1.getIOdegree();
        g1.showIOdegree();
        cout << "-------------------------------" << endl;
        g1.DFS(); 
        cout << "-------------------------------" << endl;
        g1.BFS();
        return 0;
    }

    运行效果如下:

    还在继续完善中,希望大二学数据结构时能够用上,欢迎提出见解

  • 相关阅读:
    vim 查找文件指定内容所在位置
    tar 使用小技巧
    dpkg 安装deb包
    Jetbrains 全家桶(IDEA,PyCharm...)
    Python如何生成requirements.txt文件
    MySQL——导入数据报字段编码错误
    视图的概念、作用以及如何创建
    hive与hbase及MySQL的区别
    mysql—排序函数rank() over()、dense_rank() over()、row_num() over()
    mysql —net start mysql 命令发生系统错误5和错误1058的解决方法
  • 原文地址:https://www.cnblogs.com/bxy0516/p/9005971.html
Copyright © 2020-2023  润新知