实验五 图的物理实现(邻接矩阵)

2018-12-5更新

邻接矩阵分为有向图邻接矩阵和无向图邻接矩阵​​​​​​,矩阵元素可以仅表示相应的边是否存在,也可表示相应边的权值。

若是有向带权图的邻接矩阵,看到两种表示法,一种是不存在边的两个顶点i,j,matrix[i][j]=0或者+∞;另一种是matrix[i][i]=0,不存在边的两个顶点i,j,matrix[i][j]=+∞(i!=j)。

具体采用哪种方法是根据实际需求来的。为了方便Dijkstra算法,以下代码修改为上述第二种邻接矩阵。

--------------------------------------------------------------------------------------------------------------------------------------

2018-12-4更新

增添了memset函数对标记数组mark重置

--------------------------------------------------------------------------------------------------------------------------------------

  • 说明
  • 基于邻接矩阵实现的图

一、说明

1、以下代码实现的图,顶点为0到n-1(n为顶点数)(整数),边权为大于0的整数,邻接矩阵matrix[i][j]记录的是顶点i到顶点j的边权(大于0),若无边则为0。有向图。

2、以下代码仅供参考

二、基于邻接矩阵实现的图

1、Graph.h

#include<iostream>
using namespace std;
#include"Queue.h"
#ifndef _Graph
#define _Graph
namespace wangzhe
{
	class Graph
	{
	        private:
			void operator = (const Graph&) {}
			Graph(const Graph&) {}
		public:
			Graph() {}//构造函数 
			virtual ~Graph() {}//析构函数 
			virtual int n() =0;//顶点数目 
			virtual int e() =0;//边数目 
			virtual int first(int v) =0;//与顶点v关联的第一条边 
			virtual int next(int v,int w) =0;//与顶点v关联的在顶点w后的下一条边 
			virtual void clear()=0;//销毁一个图 
			virtual bool setEdge(int v1,int v2,int wght) =0;//设边权 
			virtual bool delEdge(int v1,int v2) =0;//删除边 
			virtual bool isEdge(int i,int j) =0;//判断是否有边 
			virtual int weight(int v1,int v2) =0;//v1-v2边的边权 
			virtual int getMark(int v) =0;//返回标记信号 
			virtual void setMark(int v,int val) =0;//标记数组中做标记 
			virtual void BFS(Graph* G,int start,Queue<int>* Q) =0;//广搜
			virtual void DFS(Graph *G,int v) =0;//深搜 
	};
}
#endif 

2、graphm.h

#include<iostream>
using namespace std;
#include"Graph.h"
#include"Queue.h" 
#include"AQueue.h"
#include"AQueue.cpp"
#ifndef _Graphm
#define _Graphm
namespace wangzhe
{
	class Graphm:public Graph
	{
		private:
			int numVertex,numEdge;
			int **matrix;
			int *mark;
		public:
			Graphm();
			~Graphm();
			void Init(int n);
			int n();
			int e();
			int first(int v);
			int next(int v,int w);
			void clear(); 
			bool setEdge(int v1,int v2,int wt);
			bool delEdge(int v1,int v2);
			bool isEdge(int i,int j);
			int weight(int v1,int v2);
			int getMark(int v);
			void setMark(int v,int val);
                        void memset();//重置mark数组 
			void BFS(Graph* G,int start,Queue<int>* Q);
			void DFS(Graph *G,int v); 
			void print();//输出邻接矩阵 
	};
}
#endif

3、Graphm.cpp

#include<iostream>
#include<iomanip>
#define UNVISITED 0
#define VISITED 1
#define INF 1<<30 
using namespace std;
#include"Graphm.h"
namespace wangzhe
{
	Graphm::Graphm()
	{
		
	}
	
	Graphm::~Graphm()
	{
		clear(); 
	}
	
	void Graphm::Init(int n)
	{
		numVertex=n;
		numEdge=0;
		mark=new int[n];
		for(int i=0;i<numVertex;i++)
			mark[i]=UNVISITED;
		matrix=(int**) new int*[numVertex];
		for(int i=0;i<numVertex;i++)
	    	matrix[i]=new int[numVertex];
	        for(int i=0;i<numVertex;i++)
	    	        for(int j=0;j<numVertex;j++)
	    		{
	    			if(i==j) matrix[i][j]=0;
	    			else matrix[i][j]=INF;
			}
	}
	
	int Graphm::n()
	{
		return numVertex;
	}
	
	int Graphm::e()
	{
		return numEdge;
	}
	
	int Graphm::first(int v)
	{
		for(int i=0;i<numVertex;i++)
			if(matrix[v][i]!=INF&&matrix[v][i]!=0) return i;
		return numVertex;
	}
	
	int Graphm::next(int v,int w)
	{
		for(int i=w+1;i<numVertex;i++)
			if(matrix[v][i]!=INF&&matrix[v][i]!=0) return i;
		return numVertex;
	}
	
	void Graphm::clear()
	{
		delete [] mark;
		mark=NULL;//释放后置空 
		for(int i=0;i<numVertex;i++) 
			delete [] matrix[i];
		delete [] matrix;
		matrix=NULL;//释放后置空 
	}
	
	bool Graphm::setEdge(int v1,int v2,int wt)
	{
		if(wt<=0)
		{
			cout<<"Illegal weight value\n";
			return false;
		}
		if(v1==v2||v1<0||v2<0||v1>=numVertex||v2>=numVertex)
		{
			cout<<"Illegal vertex\n";
			return false;
		}
		if(matrix[v1][v2]==INF) numEdge++;
		matrix[v1][v2]=wt;
		return true;
	}
	
	bool Graphm::delEdge(int v1,int v2)
	{
		if(v1<0||v2<0||v1>=numVertex||v2>=numVertex||v1==v2)
		{
			cout<<"Illegal vertex\n";
			return false;
		}
		if(matrix[v1][v2]!=INF) numEdge--;
		matrix[v1][v2]=INF;
		return true;
	}
	
	bool Graphm::isEdge(int i,int j)
	{
		if(i==j||matrix[i][j]==INF) return false;
		return true;
	}
	
	int Graphm::weight(int v1,int v2)
	{
		if(v1<0||v2<0||v1>=numVertex||v2>=numVertex||v1==v2)
		{
			cout<<"Illegal vertex\n";
			return INF;
		}
		return matrix[v1][v2];
	}
	
	int Graphm::getMark(int v)
	{
		return mark[v];
	}
	
	void Graphm::setMark(int v,int val)
	{
		mark[v]=val;
	}
	
	void Graphm::memset()
	{
		for(int i=0;i<numVertex;i++)
			mark[i]=UNVISITED;	
	}
	
	void Graphm::BFS(Graph* G,int start,Queue<int>* Q)
	{
		Q->enqueue(start);
		G->setMark(start,VISITED);
		while(Q->length())
		{
			int v=Q->dequeue();
			cout<<v<<' ';//previsit
			for(int w=G->first(v);w<G->n();w=G->next(v,w))
			{
			        if(G->getMark(w)==UNVISITED)
				{
					G->setMark(w,VISITED);
					Q->enqueue(w);
				}	
			} 
		}
	}
	
	void Graphm::DFS(Graph* G,int v)
	{
		cout<<v<<' ';//previsit
		G->setMark(v,VISITED);
		for(int w=G->first(v);w<G->n();w=G->next(v,w))
		{
			if(G->getMark(w)==UNVISITED)
				DFS(G,w);
		}
	}
	
	void Graphm::print()
	{
		if(matrix==NULL) 
		{
			cout<<"Empty graph\n";
			return;
		}
	        for(int i=0;i<numVertex;i++)
		{
			for(int j=0;j<numVertex;j++)
			{
				if(matrix[i][j]==INF) cout<<setw(5)<<"∞";
				else cout<<setw(5)<<matrix[i][j];
			}	
			cout<<endl;
		}	
	} 
}

4、Queue.h
5、AQueue.h
6、AQueue.cpp
参考队列的物理实现(顺序队列+链式队列)

7、main.cpp

#include <iostream>
using namespace std;
#define INF 1<<30
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
#include"Graphm.h"
#include"AQueue.h"
//#include"AQueue.cpp"
using namespace wangzhe;
int main(int argc, char** argv) 
{
	for(int i=1;i<=50;i++) cout<<'*';
        cout<<"\n实验五:图的物理实现(邻接矩阵)\n";
	for(int i=1;i<=50;i++) cout<<'*';
	cout<<endl;
	cout<<"请输入对应的数字实现相关操作:\n";
	cout<<" 0、退出操作\n"; 
	cout<<" 1、新建一个图\n";
	cout<<" 2、输出当前图的邻接矩阵\n";
	cout<<" 3、增添一条边\n";
	cout<<" 4、删除一条边\n";
	cout<<" 5、判断是否有某条边\n";
	cout<<" 6、查询边权\n";
	cout<<" 7、对当前图进行宽度优先遍历\n";
	cout<<" 8、对当前图进行深度优先遍历\n";
	cout<<" 9、输出边数\n";
	cout<<"10、销毁当前图\n";
    
        int order,vertex,edge;
        int s,e,w;
        Graphm G;
	while(true)
	{
		cin>>order;
		if(!order) break;
		switch (order)
		{
			case 1:
			{
				cout<<"请分别输入图的顶点数和边数:\n";
				cin>>vertex>>edge;
				G.Init(vertex);
				for(int i=1;i<=edge;i++)
				{
					cout<<"请依次输入第"<<i<<"条边的起点、终点和边权\n"; 
					cin>>s>>e>>w;
					if(!G.setEdge(s,e,w))
					{
						cout<<"请重新输入第"<<i<<"条边\n";
						i--;continue; 
					}
					G.setEdge(s,e,w);
				}
				cout<<"新建完成!\n";
				break;
			}
			case 2:
			{
				cout<<"图的邻接矩阵为:\n";
				G.print();
				break;
			}
			case 3:
			{
				cout<<"请分别输入要增添边的起点、终点和边权:\n";
				cin>>s>>e>>w;
				while(!G.setEdge(s,e,w))
				{
					cout<<"请重新输入该条边\n";
					cin>>s>>e>>w;
				}
				break;
			}
			case 4:
			{
				cout<<"请分别输入要删除边的起点和终点\n";
				cin>>s>>e;
				while(!G.delEdge(s,e))
				{
					cout<<"请重新输入该条边\n";
					cin>>s>>e;
				}
				break;
			}
			case 5:
			{
				cout<<"请分别输入要判断边的起点和终点\n";
				cin>>s>>e;
				if(G.isEdge(s,e))
				cout<<"该边存在\n";
				else cout<<"该边不存在\n";
				break;
			}
			case 6:
			{
				cout<<"请分别输入要查询边的起点和终点\n";
				cin>>s>>e;
				while(G.weight(s,e)==INF)
				{
					cout<<"请重新输入该条边\n";
					cin>>s>>e;
				}
				cout<<G.weight(s,e)<<endl;
				break;
			}
			case 7:
			{
				cout<<"请输入宽度优先遍历的起点\n";
				cin>>s;
				AQueue<int> QAQ(101);
				G.BFS(&G,s,&QAQ); 
				cout<<endl;
                                G.memset();
				break;
			}
			case 8:
			{
				cout<<"请输入深度优先遍历的起点\n";
				cin>>s;
				G.DFS(&G,s);
				cout<<endl;
                                G.memset();
				break;
			}
			case 9:
			{
				cout<<"当前边数为:"<<G.e()<<endl;
				break;
			}
			case 10:
			{
				G.clear();
			}
			default:break;
		}
	} 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40889820/article/details/84585869
今日推荐