图与其基本算法的实现--用邻接表来存储

图主要用的数据结构是邻接表,
邻接表适用于稀疏图中,比较节省空间,如果在稀疏图中采用邻接矩阵的存储方式,容易造成空间上的浪费。



但邻接表中的边点用的是vector实现的,没有采取链式的结构(感觉这样写简单些,手动滑稽)。
主要实现了有向图的存储,而无向图只要在加边的时候把单向的边改成双向的即可。
例如:加入1-2这条无向边,只需要加一次1-2和一次2-1就可以了。
实现的功能主要有:
邻接表的创建,深度优先搜索(递归dfs和非递归dfs),广度优先搜索(bfs),以及求点的出度的入度
//
//  main.cpp
//  图
//
//  Created by Mr chen on 2019/3/15.
//  Copyright © 2019 Mr chen. All rights reserved.
//

/*
    stl版
    利用现有stack和queue实现的
    图采取的数据结构:邻接表
    邻接表用vector来实现
    有向图
    最大点数为107
    点下标输入默认从零开始,处理数据按从0开始
*/

#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>

const int maxn = 1e2+7;
using namespace std;

typedef char vertextype;    //定义顶点的存储类型
typedef int arctype;    //定义边的权值类型

struct ANode  //边表节点
{
    int id; //邻接点域,存储该顶点对应的下标
    arctype wigth;  //用于存储权值
};

struct VNode   //顶点表节点
{
    int id;
    string data;    //存储顶点数据的信息
    vector<ANode> q;    //每个点与之相邻接的点与权值
};

class Graph
{
private:
    int sum=0;//统计点访问次数
    VNode VNodeList[maxn];//顶点表节点,存放每个点信息
    bool vis[maxn];
    int in[maxn],out[maxn];
public:
    int pointnum,eagenum;//点数,边数
    Graph(int n,int m);
    void initdfs();
    void initdegree();
    void rec_dfs(int begin);
    void nonrec_dfs(int begin);
    void bfs(int begin);
    int is_connected();
    int get_degree();
    //TODO:(5)输入顶点x,查找图G:若存在含x的顶点,则删除该结点及与之相关连的边,并作DFS遍历(执行操作3);否则输出信息“无x”;
    void print_degree();
    void print();
};

Graph::Graph(int n,int m)//构造函数,输入
{
    this->pointnum=n,this->eagenum=m;
    //printf("请输入%d个点的名字:\n",n);
    for(int i=0;i<this->pointnum;i++)
    {
        //printf("第%d个点的名称为:",i);
        cin>>VNodeList[i].data;
        VNodeList[i].id=i;
    }
    //printf("请输入%d个边的信息,格式:起点编号 终点编号 权值:\n",m);
    int begin,end,wight;
    for(int i=0;i<this->eagenum;i++)
    {
        //printf("第%d条边的信息:",i);
        cin>>begin>>end>>wight;
        VNodeList[begin].q.push_back( {end,wight} );
    }
}

void Graph::initdfs()
{
    sum=0;
    memset(vis, 0, sizeof(vis));
}

void Graph::initdegree()
{
    memset(out,0, sizeof(out));
    memset(in,0, sizeof(in));
}

void Graph::rec_dfs(int n)
{
    cout<<VNodeList[n].data<<endl;
    sum++;
    vis[n]=1;
    if(sum>=this->pointnum)
        return;
    for(vector<ANode>::iterator it=VNodeList[n].q.begin();it<VNodeList[n].q.end();it++)
    {
        if(!vis[it->id])
        {
            rec_dfs(it->id);
        }
    }
}

void Graph::nonrec_dfs(int n)
{
    initdfs();//初始化vis数组
    stack<VNode> Stack;
    Stack.push(VNodeList[n]);//根节点入栈
    vis[n]=1;
    while(!Stack.empty())
    {
        VNode tmp = Stack.top();
        Stack.pop();
        cout<<tmp.data<<endl;
        for(vector<ANode>::iterator it=VNodeList[tmp.id].q.begin();it<VNodeList[tmp.id].q.end();it++)
        {
            if(!vis[it->id])
            {
                Stack.push(VNodeList[it->id]);//未入栈的邻接点入栈
                vis[it->id]=1;
            }
        }
    }
}

void Graph::bfs(int n)
{
    initdfs();
    queue<VNode> Queue;
    Queue.push(VNodeList[n]);
    while(!Queue.empty())
    {
        VNode tmp = Queue.front();
        Queue.pop();
        cout<<tmp.data<<endl;
        for(vector<ANode>::iterator it=VNodeList[tmp.id].q.begin();it<VNodeList[tmp.id].q.end();it++)
        {
            if(!vis[it->id])
            {
                Queue.push(VNodeList[it->id]);//未入队列的邻接点入队列
                vis[it->id]=1;
            }
        }
    }
}

int Graph::is_connected()
{
    initdfs();
    int ans = 0;
    for(int i=0;i<pointnum;i++)
    {
        if(!vis[i])
        {
            rec_dfs(i);
            ans++;
        }
    }
    return ans;
}

int Graph::get_degree()
{
    for(int i=0;i<pointnum;i++)//求出度
    {
        out[i] = VNodeList[i].q.size();
    }
    for(int i=0;i<pointnum;i++)
    {
        for(vector<ANode>::iterator it=VNodeList[i].q.begin();it<VNodeList[i].q.end();it++)
        {
            in[it->id]++;
        }
    }
    return 0;
}

void Graph::print_degree()
{
    printf("名称 出度 入度:\n");
    for(int i=0;i<pointnum;i++)
    {
        cout<<VNodeList[i].data<<" "<<out[i]<<" "<<in[i]<<endl;
    }
}

void Graph::print()//输出
{
    for(int i=0;i<pointnum;i++)
    {
        cout<<VNodeList[i].q.end()-VNodeList[i].q.begin()<<endl;
        cout<<VNodeList[i].data<<" ";
        for(vector<ANode>::iterator it=VNodeList[i].q.begin();it<VNodeList[i].q.end();it++)
        {
            cout<<i<<" "<<it->id<<" "<<it->wigth<<"   ";
        }
        cout<<endl;
    }
}

int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        Graph mmp(n,m);
        mmp.print();
        int x;
        cin>>x;
        mmp.initdfs();
        mmp.rec_dfs(x);
        cout<<"rec_dfs end"<<endl;
        mmp.nonrec_dfs(x);
        cout<<"nonrec_dfs end"<<endl;
        mmp.bfs(x);
        cout<<"bfs end"<<endl;
        mmp.get_degree();
        mmp.print_degree();
        int connum;
        if((connum=mmp.is_connected())<=1)
            printf("This is a connected graph\n");
        else
            printf("NO!connected component is %d\n",mmp.is_connected());
    }
}

猜你喜欢

转载自blog.csdn.net/hrbust_cxl/article/details/88597806
今日推荐