270 likes | 436 Views
第7章 图. 7.2 图的存储结构. 7.2.1 邻接矩阵 int a[n][n]. 1.无向图的邻接矩阵 1 如果 ( v i , v j ) ∈ E A(i,j)= 0 其它. 2.有向图的邻接矩阵 1 如果 < v i , v j > ∈ E A(i,j)= 0 其它. 7.2.1 邻接矩阵.
E N D
第7章 图 7.2 图的存储结构
7.2.1 邻接矩阵int a[n][n] • 1.无向图的邻接矩阵 • 1 如果(vi,vj)∈E • A(i,j)= • 0 其它 • 2.有向图的邻接矩阵 • 1 如果<vi,vj>∈E • A(i,j)= • 0 其它
7.2.1 邻接矩阵 A1= A2=
邻接矩阵的特点 • (1) A(i,i)=0 1≤i≤n; • (2) 无向图的邻接矩阵是对称的 • A(i,j)=A(j,i) 1≤i≤n, 1≤j≤n; • 存入上(下)三角形,需n(n+1)/2个单元; • (3) 无向图的邻接矩阵的第i行(或第i列)非零元素的 • 个数正好是第i个顶点的度TD(vi ); • (4) 有向图的邻接矩阵一般不对称。 • 有向图需要n2个单元; • (5) 有向图的邻接矩阵的 • 第i行非零元素的个数是第i个顶点的出度OD(vi); • 第j列非零元素的个数是第j个顶点的入度ID(vi);
7.2.1 邻接矩阵int a[n][n] • 3. 网(带权值的图)的邻接矩阵 • wij i!=j 且 (vi,vj)∈E或<vi,vj>∈E • A(i,j)= ∽ i!=j ,无边或弧 • 0 i==j , 对角线元素
2 5 20 40 70 1 4 80 30 50 3 6 3. 网(带权值的图)的邻接矩阵 • 0 20 30 ∞∞∞ • 20 0∞ 40 ∞∞ • 30 ∞0 50 ∞∞ • ∞ 40 50 0 70 80 • ∞∞∞ 70 0∞ • ∞∞∞ 80 ∞0
7.2.2 邻接矩阵表示的图类 const int MaxVertices=10; const int MaxWeight=32767; class AdjMWGraph { private: int Vertices[10]; //顶点信息的数组 int Edge[MaxVertices][MaxVertices]; //边的权值信息的矩阵 int numE; //当前的边数 int numV; //当前的顶点数 public: ………; //公有函数 private: ………; //私有函数 }
class AdjMWGraph { private:…….;// 数据成员 public: AdjMWGraph(); //构造函数 void CreatG(int n,int e); //建立一个图的邻接矩阵 void PrintOut(); //输出图的邻接矩阵 void Depth(); //对连通图深度优先遍历的调用 void DepthF(); //对非连通图深度优先遍历 void Broad(); //对连通图广度优先遍历的调用 void BroadF(); //对非连通图深度优先遍历 private: void Depth(int v, int visited[]); void Broad(int v,int visited[]); };
class AdjMWGraph { private: ………; // 数据成员 public: ………..; //公有函数 private: //对连通图的深度优先遍历,visit为访问标记 void Depth(int v, int visited[]); //对连通图的广度优先遍历,visit为访问标记 void Broad(int v,int visited[]); };
//(1)构造函数 AdjMWGraph::AdjMWGraph() { for( int i=0; i i<MaxVertices; i++ ) Vertices[i]=0; for ( int i=0; i<MaxVertices; i++ ) for ( int j=0; j<MaxVertices; j++ ) { if( i==j ) Edge[i][j]=0; else Edge[i][j]=MaxWeight; //MaxWeight表示无穷 } numE=0; //当前边个数初始为0 numV=0; //当前顶点个数初始为0 }
//(2)建立一个图的邻接矩阵 void AdjMWGraph::CreatG(int n,int e) {int i,vi,vj,w; //w为边的权值 numE=e; numV=n; cout<<endl<<" 输入顶点的信息(整型):" ; for ( i=0; i<numV; i++ ) { cout<<"\n "<<i+1<<": "; cin>>Vertices[i]; } for ( i=0; i<numE; i++ ) { cout<<endl<<" 输入边的信息(vi,vj,w):"; cin>>vi>>vj>>w; Edge[vi-1][vj-1]=w; Edge[vj-1][vi-1]=w; //对于无向图 } }
//(3)输出图的邻接矩阵 void AdjMWGraph::PrintOut() { int i; cout<<"\n 输出顶点的信息(整型): "<<endl; for ( i=0; i<numV; i++ ) cout<<Vertices[i]<<" "; cout<<endl<<"\n 输出邻接矩阵:" ; for ( i=0; i<numV; i++ ) { cout<<endl<<i+1<<": "; for ( int j=0; j<numV ;j++ ) cout<<Edge[i][j]<<" "; cout<<endl; } }
在主函数中应用 //声明创建一个对象G0 //调用建立函数,4个顶点5条边 //输出邻接矩阵的信息 • int main() • { AdjMWGraphG0; • G0.CreatG(4,5); • G0.PrintOut(); • _getch(); • return 0; • }
data adj 7.2.3 邻接链表 • 1. 顶点的结构 • const int MaxVertices=100; • typedef int VerT; //顶点数据类型 • typedef int DistT; //边的数据类型 • struct item { VerT data; //顶点数据 • Edge *adj; //邻接边的指针 • }; • 2.数组(向量) • item Vertices[MaxVertices]; //顶点的数组 Item 顶点结构
dest weight next 7.2.3 邻接链表 • 3. 边的结构 • struct Edge • { int dest; //邻接顶点下标 • DistT weight; //边的权值,或更多 • Edge *next; //指针 • }; Edge 边结构
7.2.3 邻接链表 • const int MaxVertices=100; • typedef int VerT; • typedef int DistT; • struct item { VerT data; //顶点数据 • Edge *adj; //邻接边的指针 • }; • item Vertices[MaxVertices]; //顶点的数组
7.2.4 邻接链表的图类 const int MaxVertices=10; class AdjTWGraph //邻接表图类定义 { private: item Vertices[MaxVertices]; //顶点信息数组,表头向量 int numV; //顶点数组的当前元素个数 int numE; //当前边的条数 public: AdjTWGraph(); //构造函数 ~AdjTWGraph(); //析构函数 ……….; private://私有函数 }
const int MaxVertices=10; class AdjTWGraph //邻接表图类定义 {private: ……..;// public: AdjTWGraph(); //构造函数 ~AdjTWGraph(); //析构函数 void CreatG(int n,int e); //输入建立邻接表 void PrintOut(); //输出数据信息 void DepthFirst(); //调用深度优先遍历 void BroadFirst(); //调用广度优先遍历 Private: //私有函数 …………………..; }
class AdjTWGraph //邻接表图类定义 {private: ……..;// public: void DepthFirst() ; //调用深度优先遍历 void BroadFirst(); //调用广度优先遍历 private: //对连通图深度优先遍历,visit为访问标记 void DepthFirst(int v, int visited[]); //对连通图广度优先遍历,visit为访问标记 void BroadFirst(int v, int visited[]); };
//(1)构造函数 AdjTWGraph::AdjTWGraph() { for ( int i=0; i<MaxVertices; i++ ) { Vertices[i].data=0; Vertices[i].adj=NULL; } numV=0; numE=0; } Vertices[i] 0 1 0 ^ 1 0 ^ 2 0 ^ 0 ^ 3
(2)析构函数 AdjTWGraph::~AdjTWGraph(void) { for ( int i=1; i<=numV; i++ ) { Edge *p=Vertices[i].adj,*q; while ( p!=NULL) { q=p->next; delete p; p=q; } Vertices[i].adj=NULL; } } p q 1 1 1 3 2 4 ∧ 2 2 1 3 ∧ 3 3 1 2 4 ∧ 4 4 1 3 ∧
//(3)建立一个图的邻接链表 void AdjTWGraph::CreatG(int n,int e) { int vi,vj; DistT w; numE=e; numV=n; cout<<"\n 输入顶点的信息(整型):" ; for (int i=1; i<=numV; i++ ) { cout<<"\n "<<i<<": "; cin>>Vertices[i].data; } for ( int i=1; i<=numE; i++ ) { cout<<"\n 输入边的信息(顶点号vi 顶点号vj 边的权值W):"; cin>>vi>>vj>>w;
//---------------------- 在第vi条链表上,链入边(vi,vj)的结点 Edge *q=new Edge; q->dest=vj; q->weight=w; q->next=NULL; //vj是vi的邻接顶点,w是权值 if(Vertices[vi].adj==NULL) Vertices[vi].adj=q; //第一次插入 else //非第一次插入 {Edge *curr=Vertices[vi].adj, *pre=NULL; while (curr!=NULL && curr->dest<vj ) { pre=curr; curr=curr->next; } if ( pre==NULL ) //在第一个结点前插入 { q->next=Vertices[vi].adj; Vertices[vi].adj=q; } else {q->next=pre->next; //在其他位置插入 pre->next=q; } }
//-------------------在第vj条链表上,链入边(vj,vi)的结点//-------------------在第vj条链表上,链入边(vj,vi)的结点 Edge *p=new Edge; p->dest=vi; p->weight=w; p->next=NULL; if(Vertices[vj].adj==NULL) Vertices[vj].adj=p; //第一次插入 else //非第一次插入 {Edge *curr=Vertices[vj].adj,*pre=NULL; while (curr!=NULL && curr->dest<vi ) { pre=curr; curr=curr->next; } if ( pre==NULL ) //在第一个结点前插入 { p->next=Vertices[vj].adj; Vertices[vj].adj=p; } else { p->next=pre->next; //在其他位置插入 pre->next=p; } } } //for } //函数结束
//(4)输出图的邻接表信息函数 void AdjTWGraph::PrintOut() { Edge *pre,*curr; for ( int i=1; i<=numV; i++ ) { cout<<"\n 输出顶点编号信息、邻接点编号和边权值:"; cout<<setw(3)<<i<<setw(6)"<<Vertices[i].data; curr=Vertices[i].adj; while ( curr!=NULL ) {cout<<" v"<<curr->dest<<" w"<<curr->weight; curr=curr->next; } cout<<endl; }//for }// PrintOut()
在主函数中应用 //声明创建一个对象G0 //调用建立函数n0个顶点e0条边 //输出邻接矩阵的信息 • int main() • { AdjTWGraphG0; • int n0,e0; • cin>>n0>>e0; • G0.CreatG(n0,e0); • G0.PrintOut(); • _getch(); • return 0; • }