图主要用的数据结构是邻接表,
邻接表适用于稀疏图中,比较节省空间,如果在稀疏图中采用邻接矩阵的存储方式,容易造成空间上的浪费。
但邻接表中的边点用的是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());
}
}