1.相关概念
G=(V;E) 顶点和边的关系
顶点的总数n,边的总数e
(V,V)为邻接关系,(V,E)为关联关系
若邻接顶点u和v的次序无所谓,则(u, v)为无向边,所有边均为无方向的图,即无向图,反之,有向图中均为有向边
路径pi=<v0,v1,v2,v3,v4...vk> 长度|pi|=k
简单路径,图中不含重复节点的路径,起点等于终点的路径为环路
有向无环图
欧拉环路,哈密尔顿环路
2.图的表示和实现
邻接矩阵:顶点与顶点之间构成的矩阵,由于具有对称性,邻接矩阵的表示方法存在冗余
关联矩阵:顶点与边之间构成的矩阵
Vertex:包括data,入度,出度,在遍历树中的父节点,在遍历树中的优先级,顶点状态(UNDISCOVERED,DISCOVERED,VISITED)
Edge:数据,权重,类型
3.顶点静态操作
对于任意顶点i,如何枚举其所有第邻接顶点neighbor?
int nextNbr(int i,int j){ while((-1<j) && !exists(i,--j)); return j; }
确定第一个有效的邻居
int firstNbr(int i){
return nextNbr(i,n);
}
4.边操作
判断边(i,j)是否存在
int exists(int i,int j){
return (0<=i) && (i<n) && (0 <= j) && (j < n) && E[i][j] != NULL;
}
边插入
void insert(Te const& edge, int w,int i,int j){
if(exists(i,j)) return; //忽略已有的边
E[i][j] = new Edge<Te>(edge,w);
e++;
v[i].outDegree++; //更新i的初度
v[j].inDegree++; //更新j的入度
}
边删除
Te remove(int i, int j){
Te eBak = edge(i, j);
delete E[i][j];
E[i][j] = NULL;
e--;
v[i].outDegree--;
v[j].inDegree--;
return eBak;
}
邻接矩阵的空间利用率较低。
平面图:不相邻的面不相交
化繁为简(采用广度优先搜索,进行遍历搜索)
graph--->tree--->sequence
始自顶点s的广度优先搜索:
访问顶点s
依次访问s所有尚未访问的邻接顶点
依次访问它们尚未访问的邻接顶点
。。。
如此反复
直至没有尚未访问的邻接顶点
图的广度优先遍历,等于树的层次遍历
void BFS(int v, int & clock){
Queue<int> Q;
status(v)=DISCOVERED;
Q.enqueue(v);
while(!Q.empty()){
int v=Q.dequeue();
dTime(v) = ++clock;
for(int u=firstNbr(v); -1<u; u=nextNbr(v, u)){
if(UNDISCOVERED == status(u)){
status(u)=DISCOVERED;
Q.enqueue(u);
status(v,u)=TREE;
parent(u)=v;
}else
status(v,u)=CROSS
}
status(v)=VISITED;
}
}