第六章小结 图结构
图结构这一章真的非常有难度,我其实没有理解太透,作业实践题都没有做出来,所以这一章的博客写写第六章的心得。
图G=(V,E)由V顶点集合和E边集合构成。
(1)一些重要的基本概念:
- 权和网:边上的数值为权,带权的图称为网。
- 度,入度和出度:顶点v的度是指和v’相关联的边的数目。入度是以顶点v为头的弧的数目,出度是以v为尾的弧的数目。
- 路径和路径长度:在无向图中,从顶点v到顶点v’ 的路径是顶点序列。如果是有向图,路径也有向。路径长度是一条路径上经过的边和弧的数目。
- 连通,连通图和连通分量:在无向图中,如果从顶点v到顶点v’ 有路径,则为连通。图中任意两个顶点都是连通的,则为连通图。连通分量,无向图中的极大连通子图。
- 强连通图和强连通分量:在有向图中,连通图称为强连通图,连通分量称为强连通分量。
- 连通图的生成树:一个极小连通子图,含有图中全部顶点,但只有n-1条边,称为连通图的生成树。
(2)非常重要的图的存储结构:
1.邻接矩阵:
#define MaxInt 32767 #define MVNum 100 typedef struct{ char vexs[MVNum];//顶点表 int arcs[MVNum][MVNum];//邻接矩阵 int vexnum,arcnum;//图的当前点数和边数 }AMGraph;
优点:(1)便于判断两点之间是否有边(2)便于计算各顶点的度
缺点:(1)不便于增添和删除顶点操作。(2)不便于统计边的数目(3)空间复杂度为O(n2 ).
2.邻接表:(链式存储结构)
#define MVNum 100 typedef struct ArcNode//边结点 { int adjvex;//该边所指向的顶点的位置 struct ArcNode *nextarc;//指向下一条边的指针 int info;//和边相关的信息 }ArcNode; typedef struct VNode//顶点信息 { char data; ArcNode *firstarc;//指向第一条依附该顶点的边的指针 }VNode,AdjList[MVNum];//邻接表 typedef struct { AdjList vertices; int vexnum,arcnum;//图当前的顶点数和边数 }ALGraph;
优点:(1)便于增删顶点(2)便于统计边的数目(3)空间效率高
缺点:(1)不变判断是否有边(2)不便计算有向各顶点的度。
3.十字链表
4.邻接多重表
(3)关于图的一些重要操作:
1.创建图:
(1)基于邻接矩阵的创建
int CreateUDN(AMGraph &G) { int i,j,k,w,v1,v2; cin>>G.vexnum>>G.arcnum;//输入总顶点数总边数 for( i=0;i<G.vexnum;++i) cin>>G.vexs[i]; for(int i=0;i<G.vexnum;++i)//初始化邻接矩阵,边值均为最大值 for( j=0;j<G.vexnum;++j) G.arcs[i][j]=MaxInt; for( k=0;k<G.arcnum;++k)//构造邻接矩阵 { cin>>v1>>v2>>w; i=locatevex(G,v1);//确定v1,v2的位置,数组下标 j=locatevex(G,v2); G.arcs[i][j]=w; G.arcs[j][i]=G.arcs[i][j]; } return 1; }
(2)基于邻接表的创建
int CreateUDG(ALGraph &G) { int i,j,k,v1,v2; ArcNode *p1,*p2; cin>>G.vexnum>>G.arcnum; for(i=0;i<G.vexnum;++i) //构造表头结点表 { cin>>G.vextices[i].data; G.vextices[i].firstarc=NULL;//初始化表头结点的指针域为NULL } for(k=0;k<G.arcnum;++k)//构造邻接表 { cin>>v1>>v2; i=locatevex(G,v1); //求v1,v2在G中的位置,下标 j=locatevex(G,v2); p1= new ArcNode;//生成新的边结点*p1 p1->adjvex=i; p1->nextarc=G.vertices[i].firstarc;//插入边表头部,头插法 G.vertices[i].firstarc=p1; p2=new ArcNode; p2->adjvex=i; p2->nextarc=G.vertices[j].firstarc; G.vertices[j].firstarc=p2; } return 1; }
2.遍历:
深度优先搜索遍历:类似树的先序遍历
广度优先搜索遍历:类似于树的层次遍历
邻接表
(1)深度优先遍历(DFS)
邻接矩阵
连通图
邻接表
(2)广度优先遍历(BFS)
邻接矩阵
图
邻接表
(1)深度优先遍历(DFS)
邻接矩阵
非连通图
邻接表
(2)广度优先遍历(BFS)
邻接矩阵
辅助数组:visit[vexnum+1]={false};
(4)最小生成树:各边代价之和最小的生成树。
1.普里姆算法(加点法):
U集合,V-U集合,一个顶点在U中,另一个顶点在V-U中,这两个顶点的边的权值
选择,加入U集合,刷新U,V-U集合。
辅助数组:closedge[MVNum]
初始化:将各边权值都置为无穷大(邻接矩阵)
初态:在U,V-U中的最小权值的边进入刷新
流程:在每一次刷新后,找到与U中顶点邻接的所有邻接点,比较,最小权值边所在的两个顶点的V-U中的顶点进入U中,剩下的顶点保持,等待下一次刷新对比大小
终态:所有V-U中的顶点都进入到U中,U=V.
2.克鲁斯卡尔算法(加边法):
权值大小排列,从小到大排列,存入数组Edge中,在该数组中找权值最小的边,若该边依附的两个顶点属于同一个连通分量,则选择下一条最小权值边。若不同连通分量,则输出该边。
(5)最短路径算法:
迪杰斯特拉:以最短路径长度递增的次序求得各路径。
弗洛伊德:将vi 到vj 的路径长度初始化,然后进行n次比较和更新
后面的都不太懂了。
所以这一章我觉得 还是比较难的,要好好复习才行。
接下来,我想,还是好好学习书中剩下的内容,第七和第八章,还有还是要提高自己编程的水平,把这章 的编程题好好完成。