探索邻接表

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

所以我想试试看用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;
}

运行效果如下:

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

posted @ 2018-05-08 00:16  AyaHiro  阅读(...)  评论(...编辑  收藏