学习 严蔚敏讲数据结构笔记15
来源:互联网 发布:做淘宝仓库打包员累吗 编辑:程序博客网 时间:2024/05/19 13:58
广度优先搜索遍历图
从图中的某个顶点V0出发,并在访问此顶点之后依次访问V0的所有未被访问的邻接点,之后按这些顶点被访问的先后次序依次访问它们的邻接点,直至图中所有和V0有路径相通的顶点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作为起始点,重复上述过程,直至图中所有顶点都被访问到为止。
26_002
void BFSTraverse(Graph G, Status(* Visit)(int v))
{
for(v = 0; v < G.vexnum; ++ v)
{
visited[v] = FALSE;
}
InitQueue(Q); //置空的辅助队列Q
for(v = 0; v < G.vexnum; ++ v)
{
if(! visited[v])
{
//v尚未访问
EnQueue(Q, v); //v入队列
visited[u] = TRUE;
Visti(u); //访问u
while(! QueueEmpty(Q))
{
DeQueue(Q, u); //对头元素的出队并置u
//访问u
for(w = FirstAdjVex(G, u); w != 0; w = NextAdjVex(G, u, w))
{
if(! visited[w])
{
EnQueue(Q, w);
visited[w] = TRUE;
Visit(w);
}
//u的尚未访问的邻接顶点w入队列Q
}
};
}
}
}//BFSTraverse
遍历的简单应用
1. 求一条从顶点i到顶点s的简单路径
27_001
void DFSearch(int v, int s, char *PATH)
{
//从第v个顶点出发递归地深度优先遍历图G
//求得一条从v到s的简单路径,并记录在PATH中
visited[v] = TRUE; //访问第v个顶点
Append(PATH, getVertex(v));
for(w = FirstAdjVex(v); w != 0 && !found; w = NextAdjVex(v))
{
if(w = s)
{
found = TRUE;
Append(PATH, W);
}
else
{
if(! visited[w])
{
DFSearch(w, LP);
}
}
if(! found)
{
Delete(PATH);
}
}
}
2. 求两个顶点之间的一条路径长度最短的路径
基于广度优先搜索遍历,并修改链队列的结点结构及其入队列和出队列的算法。
1) 将链队列的结点改为“双链”结点,即结点中包含next和priou两个指针;
2) 修改入队列的操作,插入新的的队尾结点时,令其priou域的指针指向刚刚出队列的结点,即当前的对头指针所指结点;
3) 修改出队列的操作,出队列时,仅移动对头指针,而不将对头结点从链表中删除。
27_003
typedef DuLinkList QueuePtr;
void InitQueue(LinkQueue &Q)
{
Q.front = Q.rear = (QueuePtr) malloc (sizeof(QNode));
Q.front->next = Q.rear->next = NULL;
}
void EnQueue(LinkQueue &Q, QelemType e)
{
p = (QueuePtr) malloc(sizeof(QNode));
p->data = e;
p->next = NULL;
p->priou = Q.front;
Q.rear->next = p;
Q.rear = p;
}
void DeQueue(LinkQueue &Q, QelemType &e)
{
Q.front = Q.front->next;
e = Q.front->data;
}
7.4 最小生成树
问题:假设要在n个城市之间建立通讯网络,则连同n个城市只需要修n-1条线路,如何在最节省经费的前提下建立这个通讯网?
该问题等价于:构造网的一棵最小生成树,即:在e条带权的边中选取n-1条(不构成回路),使“权值之和“为最小。
算法一:(普里姆算法)
可取图中任意一个顶点v作为生成树的根,之后若要网生成树上添加顶点w,则在顶点v和顶点w之间必定存在一条边,并且该边的权值在所有连同顶点v和w之间的边中取最小值。
一般情况下,假设n个顶点分成两个集合:U(包含已落在生成树上的结点)和V-U(尚未落在生成树上的顶点),则在所有连通U中顶点和V-U中顶点的边中选取权值最小的边。
记录从顶点集U到V-U的代价最小的边的辅助数组:
27_004
struct
{
VertexType adjvex;
VRTyped lowcost;
}closedge[MAX_VERTEX_NUM];
k = LocateVex(G, u);
for(j = 0; j < G.vexnum; ++ j)
{
//辅助数组初始化
if(j != k)
{
closedge[j] = (u, G.arcs[k][j].adj);
}
closeedge[k].lowcoset = 0; //初始,U-(u)
for(j = 0; i < G.vexnum; ++ i)
{
//在其余顶点中选择
k = minimum(closedge); //求出T的一个小节点(k)
printf(colsedge[k].adjvex, G.vexs[k]);
closedge[k].lowcost = 0; //第k顶点并入U集
for(j = 0; j < G.vexnum; ++ j)
{
if(G.arcs[k][j].adj < closedge[j].lowcost)
{
closedge[j] = (G.vexs[k], G.arcs[k][j].adj);
}
}
}
}
算法二:(克鲁斯卡尔算法)
为使生成树上边的权值之和最小,显然,其中每一台边的权值应该尽可能地小。克鲁斯卡尔算法的做法吉局势:先构造一个只含有n个顶点的子图SG,然后从权值最小的边喀什,若它的添加不使SG中产生回路,则在SG上加上这条边,如此重复,直至加上n-1条边为止。
算法:
构造非连通图ST=(V,{});k=i=0; while(k<n-1){++I;从边集E中选取第i条权值最小的边(u,v);若(u,v)加入ST后不会使ST中产生回路,则输出边(u,v);且k++;}
由于普里姆算法的时间复杂度为O(n2),则适用于稠密图;而克鲁斯卡尔算法则需对e条边按权值进行排序,其时间复杂度为O(eloge),则适用域稀疏图。
7.5重(双)连通图和关节点
问题:若从一个连通图中删去任何一个顶点及其相关联的边,它仍为一个连通图的话,则该连通图被称为重(双)连通图。
若连通图中的某个顶点和其相关联的边被删去之后,该连通图被分割成两个或两个以上的连同分量,则称此顶点为关节点。
没有关节点的连通图为双连通图。
关节点的特征:
假设从某个顶点V0出发对连通图进行深度优先搜索遍历,则可得到一棵深度优先生成树,树上包含图的所有顶点。
若生成树的根结点,有两个或两个以上的分支,则此顶点(生成树的根)必为关节点;
对生成树上的任意一个“顶点”,若其某棵子树的跟或子树中的其它“顶点”没有和其祖先相通的回边,则该“顶点”必为关节点。
1) 设V0为深度优先遍历的出发点
28_001
p = G.vertices[0].firstarc;
v = p->adjvex;
DFSArticul(G, v); //从第v顶点出发深度优先搜素
if(count < G.vexnum)
{
//生成树的根至少有两棵子树
printf(0, G.vertices[0].data);//根是关节点
}
2) 对生成树上的顶点定义一个函数
29_002
low(v)=Min{visited[v], low[w], visted[k]}
对顶点v,若(在生成树上)存在一个子树根w,且low[w]>=visited[v]则顶点v为关节点。
对深度优先遍历算法作如下修改:
1. visited[v]的值改为遍历过程中顶点的访问次序count值
2. 遍历过程中求得low[v]=Min{visited[v],low[w],visited[k]}
3. 从子树遍历返回时,判别low[w]>=visited[v]?
29_003
min = visited[v0] = ++count; //设定low[v0]的初始值count计顶点访问次序
for(p = G.vertices[v0].firstarc; p; p=p->nextarc)
{
w = p->adjvex; //w为v0的邻接顶点
if(visited[w] == 0)
{
//w未曾访问
DFSArticul(G, w); //返回前求得low[w]
if(low[w] < min)
{
min = low[w];
if(low[w] >= visited[v0])
{
printf(v0, G.vertices[v0].data); //输出关节点
}
}
}
else
{
//w是回边上的顶点
if(visited[w] < min)
{
min = visited[w];
}
}
low[v0] = min;
}
- 学习 严蔚敏讲数据结构笔记15
- 学习 严蔚敏讲数据结构笔记01
- 学习 严蔚敏讲数据结构笔记02
- 学习 严蔚敏讲数据结构笔记03
- 学习 严蔚敏讲数据结构笔记04
- 学习 严蔚敏讲数据结构笔记05
- 学习 严蔚敏讲数据结构笔记06
- 学习 严蔚敏讲数据结构笔记07
- 学习 严蔚敏讲数据结构笔记08
- 学习 严蔚敏讲数据结构笔记09
- 学习 严蔚敏讲数据结构笔记10
- 学习 严蔚敏讲数据结构笔记11
- 学习 严蔚敏讲数据结构笔记12
- 学习 严蔚敏讲数据结构笔记13
- 学习 严蔚敏讲数据结构笔记14
- 学习 严蔚敏讲数据结构笔记16
- 学习 严蔚敏讲数据结构笔记17
- 学习 严蔚敏讲数据结构笔记18
- 数组排序,无须二次扫描
- 学习 严蔚敏讲数据结构笔记11
- 学习 严蔚敏讲数据结构笔记12
- 学习 严蔚敏讲数据结构笔记13
- 学习 严蔚敏讲数据结构笔记14
- 学习 严蔚敏讲数据结构笔记15
- 学习 严蔚敏讲数据结构笔记16
- 学习 严蔚敏讲数据结构笔记17
- 学习 严蔚敏讲数据结构笔记18
- 学习 严蔚敏讲数据结构笔记19
- 学习 严蔚敏讲数据结构笔记20
- 黑马训练营——java内存分配
- loadrunner常见问题汇总
- .net中获取周一、月初、月末、年初、年末