图的表示和实现1(图的矩阵表示法)

来源:互联网 发布:hibernate源码分析 编辑:程序博客网 时间:2024/06/02 03:18

邻接矩阵:

邻接矩阵是用矩阵来表示顶点之间的相邻关系的一种方法。A[i,j]=1则是图的边。若A[i,j]=0,则不是图的边。若G是网络则A[i,j] = wij;   wij表示边上的权值,若A[i,j]=0或无穷则计算机允许的大于所有边上权值的数。

邻接矩阵表示带权图类:

除了采用二维数组存储用于表示顶点间相邻关系的邻接矩阵外,通常还需要用一个顺序表来存储顶点信息。

vertexlist是一个顺序表,存储图的顶点集和,adjmatrix是一个动态二维数组,存储图的邻接矩阵,size表示二维数组容量,vertCount表示图的顶点数

#include<iostream>using namespace std;struct Edge  //带权值的边{  int start;  //边的起点  int dest;  // 边的终点  int weight;  //边的权值  friend ostream& operator<<(ostream& out,Edge &e);};ostream& operator <<(ostream& out,Edge &e){out<<"("<<e.start<<","<<e.dest<<","<<e.weight<<")";return out;}#include "SeqQueue.h"template<class T>class AbstractGraph  //抽象图类{public:virtual int VertexCount() = 0;  //返回顶点数,纯虚构函数,由子类实现 virtual T Get(int i) = 0;  //返回顶点vi的数据域virtual int GetFirstNeighbor (int v) = 0;  // 返回顶点v的第一个邻接顶点的序号virtual int GetNextNeighbor(int v, int w) = 0;   //返回顶点v在w后的下一个邻接顶点的序号void DFSTraverse(int v);  //从顶点v出发对非连通图进行一次深度优先搜索遍历void BFSTraverse(int v);  // 从顶点v出发对非连通图进行一次广度优先搜索遍历private:void depthfs(int v,bool visited[]);  //从顶点v出发的一次深度优先搜索遍历void breadthfs(int v,bool visited[]);  //从顶点v出发的一次广度优先搜索遍历};#include"Edge.h"  // 边类#include"SequenceList.h"   //顺序表类#include"AbstractGraph.h"  //抽象图类template<class T>class AdjMatrixGraph:public AbstractGraph<T>  //邻接矩阵表示的带权图类,继承抽象图类{private:SequenceList<T> vertexlist;  //顺序表存储图的顶点集和,已执行构造函数int **adjmatrix;  // 图的邻接矩阵,动态二维数组int size;  // 二维数组的容量int vertcount;   //顶点数,vertCount<=sizevoid Initial(int size);  //初始化图的邻接矩阵表示public:AdjMatrixGraph(int size = 10);  //构造方法,size指定二维数组的容量AdjMatrixGraph(T vertices [],int vertcount,Edge edges[],int edgeCounT);  //以顶点集和和边集和构造一个图~AdjMatrixGraph ();int VertexCount();  //返回顶点数T Get(int i);  //返回顶点vi的数据元素void InsertEdge(int i,int j,int weight);  //插入一条权值为weight的边bool InsertEdge(Edge edge);  //插入一条边friend ostream& operator <<(ostream& out,AdjMatrixGraph<T> &graph);  //输出图的顶点集合和邻接矩阵bool RemoveEdge(int i,int j);  //删除边指定顶点序号bool RemoveVertex(int v, T &old);  //删除序号为v的顶点及其相关联的边int GetFristNeighbor(int v);  //返回顶点v的第一个邻接顶点的序号int GetNextNeighbor(int v,int w);  // 返回v在w后的下一个邻接顶点的符号void MinSpanTree_prim(Edge *mst);  //构造带权图最小生成树的普里姆算法void ShortestPath(int v);  //以Dijkstra算法求带权图中顶点的单源最短路径void ShortestPa();   //以Floyd算法求带权图中每对顶点之间的最短路径};const int MAX_WEIGHT = 9999;//  最大权值
带权值的边结构体:

#include<iostream>using namespace std;struct Edge  //带权值的边{  int start;  //边的起点  int dest;  // 边的终点  int weight;  //边的权值  friend ostream& operator<<(ostream& out,Edge &e);};ostream& operator <<(ostream& out,Edge &e){out<<"("<<e.start<<","<<e.dest<<","<<e.weight<<")";return out;}

图的构造和析构函数:

template<class T>AdjMatrixGraph<T>::~AdjMatrixGraph()  //顺序表vertexlist析构已由SeqList类实现{  for(int i=0;i<size;i++)  // 释放动态二维数组占用的内存空间  delete(adjmatrix[i]);  delete(adjmatrix);}template<class T>int AdjMatrixGraph<T>::VertexCount()  //返回顶点数{   return vertcount;}template<class T>T AdjMatrixGraph<T>::Get(int i){return vertexlist.Get(i);}template<class T>ostream& operator<<(ostream& out,AdjMatriGraph<T>&graph){   out<<"顶点集合:"<<graph.vertexlist<<"领接矩阵:\n";   int n = graph.vertcount;   for(int i = 0;i<n;i++)   {       for(int j=0;j<n;j++)   if(graph.adjmatrix[i][j] == MAX_WEIGHT)   out<<"  无穷";   else   out<<"  "<<graph.adjmatrix[i][j];   out<<" \n";   }   return out;}
图的插入操作:
插入一个顶点vertex,就是在顶点的顺序表vertexlist最后插入一个新的元素vertex,顺序表容量不足的情况下将自动扩充容量,同时根据二维数组的情况自动扩充邻接矩阵的容量。

template<class T>void AdjMatrixGraph<T>::InsertVertex(T vertex)  //插入一个顶点{    vertexlist.insert(vertex);  //在顺序表最后插入一个元素vertcount++;if(vertcount>size){   int **temp = adjmatrix;   adjmatrix = new int *[size*2];  //二叉树组容量扩充2倍   int i,j;   for(i=0;i<size;i++)   {     adjmatrix[i] = new int[size*2]; for(j = 0;j<size;j++) adjmatrix[i][j] = temp[i][j]; for(j = size;j<size*2;j++) adjmatrix[i][j] = MAX_WEIGHT;   }   for(i = size;i<size*2;i++)  // 初始化扩充的邻接矩阵   {      adjmatrix[i] = new int[size*2];  for(j = 0;j<size*2;j++)  adjmarix[i][j] = (i==j)?0:MAX_WEIGHT;   }   size*=2;}}template<class T>bool AdjMatrixGraph<T>::InsertEdge(int i, int j, int weight)  //插入一条权值为weight的边  若该边已存在,则不插入{   if(i>=0&&i<vertcount&&j>=0&&j<vertcount&&i!=j&&adjmatrix[i][j]==MAX_WEIGHT)   {      adjmatrix[i][j] = weight;  return true;   }   return false;}template<class T>bool AdjMatrixGraph<T>::InsertEdge(Edge edge)  //插入一条边{   return InsertEdge(edge.start,edge.dest,edge.weighT);}

图的删除操作:
删除图的一个顶点,除了要在顶点顺序表中删除指定顶点,还要在邻接矩阵中删除与该顶点相关联的所有边。删除vi顶点实际上就是把该点后所有的点都往前移动一个位置,同时把邻接矩阵中,第i+1至n-1列的元素均向前移动。

删除邻接矩阵中的一条边:只要将邻接矩阵中的该边的权值设置为无穷即可

template<class T>bool AdjMatrixGraph<T>::RemoveEdge(int i, int j)  //删除边成功返回true{   if(i>=0&&i<vertcount&&j>=0&&j<vertcount&&i!=j&&adjmatrix[i][j]!=MAX_WEIGHT)   {      adjmatrix[i][j] = MAX_WEIGHT;  return true;   }   return false;}

删除邻接矩阵vi的顶点

template<class T>bool AdjMatrixGraph<T>::RemoveVertex(int v, T &old){   if(v>=0&&v<vertcount&&vertexlist.remove(v,old))   {     for(int i=v;i<vertcount-1;i++) for(int j=0;j<vertcount;j++) adjmatrix[i][j] = adjmatrix[i+1][j];  //元素向前一行移动 for(int j =v;j<vertcount-1;j++) for(int i = 0;i<vertcount-1;i++) adjmatrix[i][j] = adjmatrix[i][j+1];  //元素向前一列移动 vertcount--; return true;   }   return false;}

邻接矩阵性能分析:

一个有n个顶点,e条边的图,对应的邻接矩阵使用n的平方个元素存储了e条边的信息,当n较小且e较大时,邻接矩阵的存储效率是比较高的;反之,当n较大且e远小于n平方,矩阵变成稀疏矩阵,浪费的存储空间较多。

原创粉丝点击