DenseGraph.h
#ifndef DENSEGRAPH_H_INCLUDED
#define DENSEGRAPH_H_INCLUDED
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cassert>
#include <ctime>
using namespace std;
//稠密图-邻接矩阵
class DenseGraph{
private:
int n,m;//点和边
bool directed;//有向无向
vector<vector<bool> >g;
public:
DenseGraph(int n,bool directed){
this->n=n;
this->m=0;
this->directed=directed;
for(int i=0;i<n;i++){
g.push_back(vector<bool>(n,false));
}
}
~DenseGraph(){
}
int V(){return n;}
int E(){return m;}
void addEdge(int v,int w){
assert(v>=0&&v<n);
assert(w>=0&&w<n);
if(hasEdge(v,w))
return ;
g[v][w]=true;
if(!directed)
g[w][v]=true;
m++;
}
bool hasEdge(int v,int w){
assert(v>=0&&v<n);
assert(w>=0&&w<n);
return g[v][w];
}
void show(){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
cout<<g[i][j]<<"\t";
cout<<endl;
}
}
class adjIterator{//相邻边的迭代器
private:
DenseGraph &G;
int v;
int index;//指示当前迭代到的位置
public:
adjIterator(DenseGraph &graph,int v):G(graph){//迭代的是哪个图的哪个点相邻的边
this->v=v;
this->index=-1;
}
int begin(){//要迭代的第一个元素
index=-1;//不见得第一个就是,而是应该找第一个为ture的元素
return next();
}
int next(){//从当前迭代的元素偏移,找下一个元素
for(index+=1;index<G.V();index++)
if(G.g[v][index])
return index;
return -1;
}
bool end(){//观察迭代是否终止
return index>=G.V();
}
};
};
/*
//稠密图遍历
int main()
{
int N=20;
int M=100;
DenseGraph g(N,false);
for(int i=0;i<M;i++){
int a=rand()%N;
int b=rand()%N;
g.addEdge(a,b);
}
//O(V^2)
for(int v=0;v<N;v++){
cout<<v<<" : ";
DenseGraph::adjIterator adj(g,v);
for(int w=adj.begin();!adj.end();w=adj.next())
cout<<w<<" ";
cout<<endl;
}
return 0;
}
*/
#endif // DENSEGRAPH_H_INCLUDED
SparseGraph.h
#ifndef SPARSEGRAPH_H_INCLUDED
#define SPARSEGRAPH_H_INCLUDED
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cassert>
#include <ctime>
using namespace std;
//稀疏图-邻接表
class SparseGraph{
private:
int n,m;
bool directed;
vector<vector<int> >g;
public:
SparseGraph(int n,bool directed){
this->n=n;
this->m=0;
this->directed=directed;
for(int i=0;i<n;i++){
g.push_back(vector<int >());
}
}
~SparseGraph(){
}
void addEdge(int v,int w){
assert(v>=0&&v<n);
assert(w>=0&&w<n);
g[v].push_back(w);
if(v!=w&&!directed){//&&之前处理字环边的问题,先允许有平行边
g[w].push_back(v);
}
m++;
}
bool hasEdge(int v,int w){//最坏O(n)
assert(v>=0&&v<n);
assert(w>=0&&w<n);
for(int i=0;i<g[v].size();i++){
if(g[v][i]==w)
return true;
return false;
}
}
void show(){
for(int i=0;i<n;i++){
cout<<"vertex"<<i<<":\t";
for(int j=0;j<g[i].size();j++)
cout<<g[i][j]<<"\t";
cout<<endl;
}
}
class adjIterator{//相邻边的迭代器
private:
SparseGraph &G;
int v;
int index;//指示当前迭代到的位置
public:
adjIterator(SparseGraph &graph,int v):G(graph){//迭代的是哪个图的哪个点相邻的边
this->v=v;
this->index=0;
}
int begin(){//要迭代的第一个元素
index=0;
if(G.g[v].size())
return G.g[v][index];
return -1;
}
int next(){//从当前迭代的元素偏移,找下一个元素
index++;
if(index<G.g[v].size())
return G.g[v][index];
return -1;
}
bool end(){//观察迭代是否终止
return index>=G.g[v].size();
}
};
};
/*
//稀疏图遍历
int main()
{
int N=20;
int M=100;
srand(time(NULL));
SparseGraph g1(N,false);
for(int i=0;i<M;i++){
int a=rand()%N;
int b=rand()%N;
g1.addEdge(a,b);
}
//O(E)
for(int v=0;v<N;v++){
cout<<v<<" : ";
SparseGraph::adjIterator adj(g1,v);
for(int w=adj.begin();!adj.end();w=adj.next())
cout<<w<<" ";
cout<<endl;
}
cout<<endl;
return 0;
}
*/
#endif // SPARSEGRAPH_H_INCLUDED
ReadGraph.h
#ifndef READGRAPH_H_INCLUDED
#define READGRAPH_H_INCLUDED
//C++文件读取
//可同时作用在稀疏图和稠密图上
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cassert>
using namespace std;
template <typename Graph>
class ReadGraph{
public:
ReadGraph(Graph &graph,const string &filename){
ifstream file ( filename );
string line;
int V,E;
assert(file.is_open());
assert(getline(file,line));
stringstream ss(line);
ss>>V>>E;
for(int i=0;i<E;i++){
assert(getline(file,line));
stringstream ss(line);
int a,b;
ss>>a>>b;//把ss中的内容赋给a,b
assert(a>=0&&a<V);
assert(b>=0&&b<V);
graph.addEdge(a,b);
}
}
};
/*
int main()
{
string filename= "testG1.txt";
SparseGraph g1(13,false);
ReadGraph<SparseGraph> readGraph1(g1,filename);
g1.show();
cout<<endl;
DenseGraph g2(13,false);
ReadGraph<DenseGraph> readGraph2(g2,filename);
g2.show();
return 0;
}
*/
#endif
Component.h
#ifndef COMPONENT_H_INCLUDED
#define COMPONENT_H_INCLUDED
#include <iostream>
#include <cassert>
using namespace std;
template <typename Graph>
class Component{
private:
Graph &G;
bool *visited;
int ccount;
int *id;
void dfs(int v){
visited[v]=true;
id[v]=ccount;
typename Graph::adjInterator adj(G,v);
for(int i=adj.begin();!adj.end();i=adj.next()){
if(!visited[i])
dfs(i);
}
}
public:
Component(Graph &graph):G(graph){
visited=new bool[G.V()];
id=new int[G.V()];
ccount=0;
for(int i=0;i<G.V();i++){
visited[i]=false;
id[i]=-1;
}
for(int i=0;i<G.V();i++)
if(!visited[i]){
dfs(i);
ccount++;
}
}
~Component(){
delete[] visited;
delete[] id;
}
int count(){
return ccount;
}
bool isConnected(int v,int w){
assert(v>=0&&v<G.V());
assert(w>=0&&w<G.V());
return id[v]==id[w];
}
};
#endif // COMPONENT_H_INCLUDED
Path.h
#ifndef PATH_H_INCLUDED
#define PATH_H_INCLUDED
template <typename Graph>
class Path{//寻找图中从一个点到另外一个点的路径
private:
Graph &G;
int s;
bool* visited;
int* from;//记录访问的当前节点的前一个节点
void dfs(int v){
visited[v]=true;
typename Graph::adjInterator adj(G,v);
for(int i=adj.begin();!adj.end();i=adj.next()){
if(!visited[i]){
from[i]=v;
dfs(i);
}
}
}
public:
Path(Graph &graph,int s):G(graph){
//算法初始化
assert(s>=0&&s<G.V());
visited=new bool[G.V()];
from=new int[G.V()];
for(int i=0;i<G.V();i++){
visited[i]=false;
fron[i]=-1;
}
this->s=s;
//寻路算法
dfs(s);
}
~Path(){
delete [] visited;
delete [] from;
}
bool hasPath(int w){//s->w是否有路
assert(w>=0&&w<G.V());
return visited[w];
}
void path(int w,vector<int >&vec){//s->w的路径
stack<int >s;
int p=w;
while(p!=-1){
s.push(p);
p=from(p);
}
vec.clear();
while(!s.empty()){
vec.push_back(s.top());
s.pop();
}
}
void showPath(int w){//打印路径
vector<int >vec;
path(w,vec);
for(int i=0;i<vec.size();i++){
cout<<vec[i];
if(i==vec.size()-1)
cout<<endl;
else
cout<<" -> ";
}
}
};
/*
int main()
{
string filename="testG2.txt";
SparseGraph g=SparseGraph(7,false);
ReadGraph<SparseGraph> readGraph(g,filename);
Path<SparseGraph>dfs(g,0);
cout<<"DFS: ";
dfs.showPath(6);
return 0;
}
*/
#endif // PATH_H_INCLUDED
ShortestPath.h
#ifndef SHORTESTPATH_H_INCLUDED
#define SHORTESTPATH_H_INCLUDED
template <typename Graph>
class ShortestPath{//bfs求无权图的最短路径
private:
Graph &G;
int s;
bool *visited;
int *from;
int *ord;//记录从s到每一个节点的最短距离
public:
ShortestPath(Graph &graph,int s):G(graph){
//算法初始化
assert(s>=0&&s<graph.V());
visited=new bool[graph.V()];
from=new int[graph.V()];
ord=new int[graph.V()];
for(int i=0;i<graph.V();i++){
visited[i]=false;
from[i]=-1;
ord[i]=-1;
}
this->s=s;
queue<int>q;
//无向图的最短路径算法
q.push(s);
visited[s]=true;
ord[s]=0;
while(!q.empty()){
int v=q.front();
q.pop();
typename Graph::adjIterator(G,v);
for(int i=adj.begin();!adj.end();i=adj.next())
if(!visited[i]){
q.push(i);
visited[i];
from[i]=v;
ord[i]=ord[v]+1;
}
}
}
~ShortestPath(){
delete [] visited;
delete [] from;
delete [] ord;
}
bool hasPath(int w){//s->w是否有路
assert(w>=0&&w<G.V());
return visited[w];
}
void path(int w,vector<int >&vec){//s->w的路径
stack<int >s;
int p=w;
while(p!=-1){
s.push(p);
p=from(p);
}
vec.clear();
while(!s.empty()){
vec.push_back(s.top());
s.pop();
}
}
void showPath(int w){//打印路径
vector<int >vec;
path(w,vec);
for(int i=0;i<vec.size();i++){
cout<<vec[i];
if(i==vec.size()-1)
cout<<endl;
else
cout<<" -> ";
}
}
int length(int w){
assert(w>=0&&w<G.V())
return ord[w];
}
};
/*
int main()
{
string filename="testG2.txt";
SparseGraph g=SparseGraph(7,false);
ReadGraph<SparseGraph> readGraph(g,filename);
ShortestPath<SparseGraph>bfs(g,0);
cout<<"BFS: ";
bfs.showPath(6);
return 0;
}
*/
#endif // SHORTESTPATH_H_INCLUDED