差点就脱更了啊,微臣嘴干玩死,忙碌的暑假,还有头痛的new house, 我这junk food 也是吃一大堆,please不要长胖啊。
图的应用 这一章内容也是很多啊,概念真是比牛毛还多。。。看了两遍才缓过来啊 fighting
有向树:当有向图中仅有1个顶点的入度为0,其余顶点的入度均为1,此时是一个有向树。
权与网:图中边或弧所具有的相关数称为权。表明从一个顶点到另一个顶点的距离或耗费。带权的图称为网。
存储表示,用两个数组分别存储定点表和邻接矩阵
#define Maxlnt 32767 // 表示极大值,即∞
#define MVNum 100 // 最大顶点数
typedef char VerTexType; // 设顶点的数据类型为字符型
typedef int ArcType; // 假设边的权值类型为整型
typedef struct{
VerTexType vexs[MVNum]; // 顶点表
ArcType arcs[MVNum][MVNum]; // 邻接矩阵
int vexnum, arcnum; // 图的当前点数和边数
}AMGraph; // Adjacency Matrix Graph
采用邻接矩阵表示法创建无向网
思想:
// 采用邻接矩阵法创建无向网
Status CreateUDN (AMGraph &G) {
cin>>G.vexnum>>G.arcnum; // 输入总顶点数,总边数
for (i=0; i>G.vex[i]; //依次输入点的信息,构造顶点表
for (i=0;i>v1>>v2>>w; 输入一条边的两个顶点以及权值
i = LocateVex(G,v1);
j = LocateVex(G,v2); // 确定v1,v2在G中位置
G.arcs[i][j] = w; //边的权值设为w
G.arcs[j][i] = G.arcs[i][j]; // 无向网(图)的对称性质
} // for
return OK;
} // craeteUDN
无向网稍加改动就可以创建无向图/有向图/有向网
邻接矩阵优点:
邻接矩阵缺点:
特点:
==> AdjList v 相当于 VNode v[MVNum]
// 邻接链表创建无向网
Status CreateUDG(ALGraph &G){
cin>>G.vexnum>>G.arcnum; // 输入顶点数、边数
for (i=0;i>G.vertices[i].data;
G.vertices[i].firstarc=NULL;
}// for
for (k=0;kv1>>v2;
i=LocateVex(G,v1); // 得到两个顶点在顶点表中的位置
j=locateVex(G,v2);
p1=new ArcNode; // 生成一个新的边结点*p1
p1->adjvex=j; // 邻接点序号为j
p1->nextarc=G.vertices[i].firstarc; // 头插法
G.vertices[i].firstarc=p1; // 新结点插入顶点vi的边表头部
p2=new ArcNode; // 无向网的对称性,相同的步骤生成新结点*p2
p2->adjvex=i;
p2->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc=p2;
}// for
return OK;
}
Orthogonal List - 有向图的另一种链式存储形式,是邻接表和逆邻接表的结合体
从已给的连通图中某一顶点出发,沿着一些边访遍图中所有的顶点,且使每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算。
实质:找每个顶点的邻接点的过程
方法:
连通图的深度优先遍历类似于树的先根遍历
非连通图的遍历和连通图一样不过是以连通分量划分,一个连通分量访问完了再访问下一个直到全部访问。
// 邻接矩阵实现深度优先遍历
void DFS(AMGraph G, int v) { // G为邻接矩阵类型
count<
结论:稠图适于在邻接矩阵上进行深度遍历, 稀疏图适于在邻接表上进行深度遍历。
// 按广度优先非递归遍历连通图G
void BFS(Graph G, int v){
count<=0; w=NextAdjVex(G,u,w)){ // 依次寻找元素u的邻接元素
if (!visited[w]){ // 邻接元素w没被访问时,标记访问flag并入队
count<
算法效率:邻接矩阵O(n2), 邻接表O(n+e) (n为元素,e为结点)
空间复杂度相同,都是O(n)(借用了堆栈或队列);时间复杂度只与存储结构(邻接矩阵或邻接表)有关,而与搜索路径无关。
定义:所有顶点均由边连接在一起,但不存在回路的图。
一个图可以有许多棵不同的生成树
所有生成树具有以下共同特点:
含 n 个顶点n-1 条边的图不一定是生成树。
最小生成树:给定一个无向网络,在该网的所有生成树中,使得各边权值之和最小的那棵生成树称为该网的最小生成树,也叫最小代价生成树。
典型应用:n个城市(顶点)间建立通信网(连通网),铺设n-1条线路(边),每条线路的花费为(权值),如何费用最小?
MST性质内容: 设 N = (V, E) 是一个连通网, U是顶点集 V 的一个非空子集。若边 (u, v) 是一条具有最小权值的边,其中 u属于U, v属于V-U, 则必存在一棵包含边 (u, v) 的最小生成树。
思想:
两种算法比较:
问题抽象:在有向网中 A 点(源点)到达 B 点(终点)的多条路径中,寻找一条各权值之和最小的路径,就是最短路径。
最短路径与最小生成树不同,路径上不一定包含n个顶点,也不一定包含n-1条边。
第一类问题:两点间最短距离
解决办法:
思想:
无环的有向图,directed Acycline Graph
注意与有向树和有向图的区别,一个顶点可以有多个前驱但是不存在环。
有向无环图常用来描述一个工程或系统的进行过程。一个工程可以分为若干个子工程,只要完成了这些子工程(活动),就可以导致整个工程的完成。
AOV网(activity on vertex network, 顶点表示活动,边表示活动之间优先级制约关系) – 拓扑排序
AOE网(activity on edge, 边表示活动,顶点表示活动的开始/结束事件) – 关键路径
特点:
若从 i 到 j 有一条有向路径,则 i 是 j 的前驱;j 是 i 的后继。
若是网中有向边,则 i 是 j 的直接前驱; j 是 i 的直接后继。
AOV 网中不允许有回路,因为如果有回路存在,则表明某项活动以自己为央条件,显然这是荒谬的。
如何判别 AOV 网中是否存在回路? ==> 拓扑排序
拓扑排序:
在 AOV 网没有回路的前提下,我们将全部活动排列成一个线性序列,使得若 AOV 网中有弧< i, j >存在则在这个序列中, i 一定排在 j的前面,具有这种性质的线性序列称为拓扑有序序列,相应的拓扑有序排序的算法称为拓扑排序。
步骤:
在有向图中选一个没有前驱的顶点且输出之。
从图中删除该顶点和所有以它为尾的弧。
重复上述两步,直至全部顶点均已输出,或者当图中不存在无前驱的顶点为止
检测 AOV 网中是否存在环方法
把工程计划表示为边表示活动的网络,即 AOE 网,用顶点表示事件,弧表示活动,弧的权表示活动持续时间。
关键路径:路径长度最长的路径。
路径长度:路径上各活动持续时间之和。
下图的概念先理解,后面要用:
l(i) - e(i)
表示完成活动 ai 的时间余量。l(3) - e(3) = 90
关键活动: 关键路径上的活动,即l(i) == e(i)
(即l(i) - e(i) = 0
)的活动
如何计算ve(j), vl(i):
讨论:
TO BE CONTINUED…