43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法

本篇名言:“辛勤的蜜蜂永没有时间悲哀。--布莱克”

这次来看下Dijkstra )算法。还是老方法,先原理,后实现。代码来自网络。

欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47046031

1.  最短路径

最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。 管道铺设、线路安排、厂区布局、设备更新等

Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。

2.  Dijkstra算法

迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。

3.  问题描述

无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短值。

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。

问题描述:在无向图G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)

4.  算法描述

设G=(V,E)是一个带权有向图,把顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

5.  算法步骤

a)        初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。

b)        从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c)        以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d)        重复步骤b和c直到所有顶点都包含在S中。

6.  代码实现

6.1         定义

定义两个结构体,通用的顶点数据结构体和顶点元素信息。

typedefstruct
_vertex{                       
//通用的顶点数据结构体

intid;//id

struct _vertex*pLinkList[MAX_EDGE_NUM];   //相邻顶点的指针数组

intnCost[MAX_VERTEX_NUM];                   //与相邻顶点的权重数组

struct _vertex**next;                       //与剩余顶点之间的最短路径

int*pmincost;                               //与剩余顶点之间的最小代价

}vertex;

typedefstruct
_node{                            //组成图的顶点元素信息进行封装

intnID;

struct _vertex*pVer;

}node;

6.2         Main

注意:运行时候需要指定1个参数。

通过InitGraphic函数来初始化图。

调用ViewGraphic函数来打印图。

调用Dijkstra函数来调用迪杰特斯拉算法。

如果调用失败,则调用UnitGraphic函数。

然后调用循环打印最优路径。

输入1打印最优路径(输入起始和结束点的ID,然后调用MinRoute函数打印最优路径。)

输入2 退出程序

其他则重新输入

退出时候调用UnitGraphic函数。

6.3         InitGraphic

根据图的信息文件,初始化数组。

文件内容如下:

1:2-2:3-4:5-4;

2:1-2:3-3;

3:1-4:2-3:5-6:6-7;

4:6-8;

5:1-4:3-6;

6:3-7:4-8;

主要内容是:

打开参数指定的文件。

先调用memset函数初始化数组内容都为0。

打开文件为只读模式。将文件内容一行读到buf中(文件每行不能超过256个字符)。

根据:来分割字符串,获取第一个字符,并转换为整型,如果小于100则继续处理,否则提示超过界限。

如果小于100,则设置数组的下一个值为该值。

根据顶点的数量,逐个获取顶点,以及顶点后方的字符串2-2 3-4 5-4等(2-2第一个2表示和第2个节点相邻,第二个2表示到第2个节点的代价)。

设置该顶点的相邻指针。

设置该顶点到该相邻顶点的cost.

将与剩余顶点之间的最小代价为NULL

将与剩余顶点之间的最路径设置为NULL

于该顶点相邻的指数自加1,遇到每行的“;”表示该点处理完毕。

循环处理完所有的顶点。

然后关闭文件。

6.4         UnitGraphic

释放在InitGraphic函数中分配的空间。

6.5         ViewGraphic

打印图的结构信息

根据所有的顶点总数进行打印。

打印该顶点的ID号,然后依次打印和该顶点链接的顶点,以及代价。

打印完毕一个顶点后,继续打印其他的顶点。

6.6         Dijkstra

该函数实现依次将每个节点作为起始节点,计算剩余节点与其之间的最短路径

具体如下:

先分配一块和顶点数量一样多的整型空间用于存放其余及诶单到起始节点的最小代价tcost。

再分配一块和顶点数量一样多的BOOL空间用于判断节点是否计算完毕pbDone。

然后从第一个节点开始,依次将每个顶点作为起始节点

先初始化其他节点到起始节点的代价为无限大(每个顶点开始都要操作该步骤)。

然后malloc储存每个顶点最优的前驱顶点的id的数组

接着malloc储存每个顶点到起始顶点的最小代价数组

考虑到本节点和本节点的特殊性(先处理之)

接着开始循环获取其余节点的代价。得到其余顶点到该节点的代价数组。

然后找出更新后,所有顶点中,代价最小的顶点(去掉无限远和距离为0的点)

如果除起始顶点外的所有节点都已经被处理完毕,则退出进入到下一个顶点的寻找旅程。

记录该点到下一层的最小代价,然后从最短路劲的那个点继续开始寻找下一层的最短路径。

处理完一个顶点后,进入到顶一个顶点处理,直到结束。

最后释放临时分配的存储空间。

其中pbegin为每次的起始顶点,在从一个顶点开始寻找最短路径的时候该值一直不变,直到以下一个顶点为开始顶点。Arr为图的数组。Nidtemp为与当前节点相邻的其它节点中,cost最小的顶点序号。

BOOL Dijkstra(nodearr[])

{

UINTi, j, k;

vertex*pbegin, *ptemp, *ptemp1;

int*tcost;//用于储存其余节点到起始节点的最小代价

BOOL*pbDone;//用于判断节点是否计算完毕的数组

intnidtemp;//与当前节点相邻的其它节点中,cost最小的顶点序号

intnmixcost = INFINITE;

tcost = (int*)malloc(g_node_num*sizeof(int));

pbDone = (BOOL*)malloc(g_node_num*sizeof(BOOL));

if(NULL== tcost ||
NULL == pbDone) {

printf("out of memory\n");

return FALSE;

}

for(i=0;arr[i].pVer!=0;i++) {//依次将每个顶点作为起始节点

for(j=0;j<g_node_num; j++) {//初始化数组

tcost[j] =
INFINITE;//其它节点到起始节点的代价

pbDone[j] = 0;

}

pbegin=
arr[i].pVer;//起始顶点

pbegin->next = (vertex**)malloc(g_node_num*sizeof(vertex*));//储存每个顶点最优的前驱顶点的id的数组

pbegin->pmincost = (int*)malloc(g_node_num*sizeof(int));//储存每个顶点到起始顶点的最小代价数组

tcost[i] = 0;//初始化

pbDone[i] = 1;

pbegin->pmincost[i] = 0;

ptemp= pbegin;//设定起始顶点为当前顶点

while(1){

for(j=0;ptemp->pLinkList[j]!=0; j++) {//遍历当前顶点的相邻节点,更新最小代价(松弛边)

ptemp1 = ptemp->pLinkList[j];

if(tcost[ptemp1->id-1] >tcost[ptemp->id-1] + ptemp->nCost[ptemp1->id-1] \

&& pbDone[ptemp1->id-1] == 0) {

tcost[ptemp1->id-1] = tcost[ptemp->id-1] +ptemp->nCost[ptemp1->id-1];

pbegin->next[ptemp1->id-1] = ptemp;//设定顶点更新后的前驱顶点

}

}

nmixcost =
INFINITE;

for(j=0;j<g_node_num; j++) {//找出更新后,所有顶点中,代价最小的顶点,重新作为当前顶点。这一步可以优化。

if(pbDone[arr[j].nID-1]!= 1 && tcost[arr[j].nID-1]<
nmixcost && tcost[arr[j].nID-1]!= 0) {

nmixcost = tcost[arr[j].nID-1];

nidtemp =
arr[j].nID;

}

}

if(nmixcost==INFINITE) {//除起始顶点外的所有节点都已经被处理完毕,退出

break;

}

pbegin->pmincost[nidtemp-1] = nmixcost;

ptemp =
arr[nidtemp-1].pVer;//重新设定当前顶点

pbDone[nidtemp-1] = 1;//表示当前顶点已经被处理过了,其路径已经最短,代价最小

}

}

free(pbDone);

free(tcost);

return TRUE;

}

6.7         MinRoute

根据设定的起始和终止节点序号,打印最小代价。

最小代价直接通过起始点的pmincost数组中提取即可。

最优路径通过回溯方法进行,通过next数组获得前驱顶点,然后前驱顶点再获得前驱顶点直到召开开始的点。

7.  源码

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#defineMAX_VERTEX_NUM100                       //最大顶点数

#defineMAX_EDGE_NUM50                           //相邻最大节点数

#defineINFINITE1E5                           //表示节点之间无连接的一个较大的数

#defineMAX_STRLEN256                           //最大字符串字节数

#defineFALSE                        0

#defineTRUE                        1

typedefint                           
BOOL;

typedefunsigned
int               
UINT;

#defineSAFEFREE(p){if(NULL!=(p))free(p);}

typedefstruct
_vertex{                       
//通用的顶点数据结构体

intid;//id

struct _vertex*pLinkList[MAX_EDGE_NUM];   //相邻顶点的指针数组

intnCost[MAX_VERTEX_NUM];                   //与相邻顶点的权重数组

struct _vertex**next;                       //与剩余顶点之间的最短路径

int*pmincost;                               //与剩余顶点之间的最小代价

}vertex;

typedefstruct
_node{                           
//组成图的顶点元素信息进行封装

intnID;

struct _vertex*pVer;

}node;

int g_node_num;/*用于计算实际节点数的全局变量*/

/****************************************

*函数名:InitGraphic

*参数:path-图的信息文件路径;arr-储存图的数组;nsize-数组大小

*返回值:BOOL-成功返回1,错误返回0

*说明:根据图的信息文件,初始化数组

*****************************************/

BOOL InitGraphic(charpath[],nodearr[],UINTnsize)

{

charbuf[MAX_STRLEN];

char*pos;

charctemp;

intncost;

inti;

UINTnid;//临时顶点ID

UINTncid;//临时连接顶点的ID

UINTnlinkpos;//连接顶点数组中的位置

memset(arr,0,sizeof(node)*nsize);//赋值0

FILE*pfile = fopen(path,
"r");

if(NULL== pfile) {

printf("Error opening file.\n");

return FALSE;

}

while(NULL!= fgets(buf,MAX_STRLEN, pfile)) {

pos =strtok(buf,
":");//读取一行,解析第一个冒号之前的标号,即第几个节点

nid =atoi(pos);

if(nid< nsize) {

arr[nid-1].nID= nid;

arr[nid-1].pVer= (vertex*)malloc(sizeof(vertex));//申请一个顶点struct

if(NULL==
arr[nid-1].pVer) {

printf("out of memory!\n");

returnFALSE;

}

memset(arr[nid-1].pVer, 0,sizeof(vertex));//赋值0

arr[nid-1].pVer->id= nid;

g_node_num++;//节点数加1

}
else {

fprintf(stderr,"accessthe boundary of setting:%d\n", nid);

}

}

rewind(pfile);//文件指针跳转到开始处,读取各顶点的相邻节点

for(i=0;i<g_node_num; i++) {

fscanf(pfile,
"%d",&nid);//读取第一个节点标号

nlinkpos = 0;//指示其相邻节点结构体的当前位置

while((ctemp=fgetc(pfile))!=
‘;‘) {

fscanf(pfile,
"%u-%d",&ncid, &ncost);

if(ncid> nsize || ncost < 0) {

fprintf(stderr,"accessthe boundary of setting or find negative cost:%u-%d\n",ncid, ncost);

returnFALSE;

}

arr[nid-1].pVer->pLinkList[nlinkpos]=
arr[ncid-1].pVer;/*相邻节点指针数组赋值*/

arr[nid-1].pVer->nCost[ncid-1]= ncost;/*此节点到相邻节点的cost*/

arr[nid-1].pVer->pmincost= NULL;

arr[nid-1].pVer->next= NULL;

nlinkpos++;

}

}

fclose(pfile);

return TRUE;

}

/*******************************************

*函数名:ViewGraphic

*参数:arr-图的数组

*返回值:无

*说明:打印图的结构信息

*******************************************/

void ViewGraphic(nodearr[])

{

inti, j;

intnidtemp;//临时节点序号

printf("\nID\tConncetedto-ID:cost");

for(i=0;i<g_node_num; i++) {

printf("\n%d\t",arr[i].nID);

for(j=0;arr[i].pVer->pLinkList[j]!=NULL; j++) {

nidtemp =
arr[i].pVer->pLinkList[j]->id;

printf("%d:", nidtemp);

printf("%d ",arr[i].pVer->nCost[nidtemp-1]);

}

}

}

/*************************************************

*函数名:Dijkstra

*参数:arr-图的数组

*返回值:TRUE-成功;FALSE-失败

*说明:依次将每个节点作为起始节点,计算剩余节点与其之间的最短路径

*************************************************/

BOOL Dijkstra(nodearr[])

{

UINTi, j, k;

vertex*pbegin, *ptemp, *ptemp1;

int*tcost;//用于储存其余节点到起始节点的最小代价

BOOL*pbDone;//用于判断节点是否计算完毕的数组

intnidtemp;//与当前节点相邻的其它节点中,cost最小的顶点序号

intnmixcost = INFINITE;

tcost = (int*)malloc(g_node_num*sizeof(int));

pbDone = (BOOL*)malloc(g_node_num*sizeof(BOOL));

if(NULL== tcost ||
NULL == pbDone) {

printf("out of memory\n");

return FALSE;

}

for(i=0;arr[i].pVer!=0;i++) {//依次将每个顶点作为起始节点

for(j=0;j<g_node_num; j++) {//初始化数组

tcost[j] =
INFINITE;//其它节点到起始节点的代价

pbDone[j] = 0;

}

pbegin=
arr[i].pVer;//起始顶点

pbegin->next = (vertex**)malloc(g_node_num*sizeof(vertex*));//储存每个顶点最优的前驱顶点的id的数组

pbegin->pmincost = (int*)malloc(g_node_num*sizeof(int));//储存每个顶点到起始顶点的最小代价数组

tcost[i] = 0;//初始化

pbDone[i] = 1;

pbegin->pmincost[i] = 0;

ptemp= pbegin;//设定起始顶点为当前顶点

while(1){

for(j=0;ptemp->pLinkList[j]!=0; j++) {//遍历当前顶点的相邻节点,更新最小代价(松弛边)

ptemp1 = ptemp->pLinkList[j];

if(tcost[ptemp1->id-1] >tcost[ptemp->id-1] + ptemp->nCost[ptemp1->id-1] \

&& pbDone[ptemp1->id-1] == 0) {

tcost[ptemp1->id-1] = tcost[ptemp->id-1] +ptemp->nCost[ptemp1->id-1];

pbegin->next[ptemp1->id-1] = ptemp;//设定顶点更新后的前驱顶点

}

}

nmixcost =
INFINITE;

for(j=0;j<g_node_num; j++) {//找出更新后,所有顶点中,代价最小的顶点,重新作为当前顶点。这一步可以优化。

if(pbDone[arr[j].nID-1]!= 1 && tcost[arr[j].nID-1]<
nmixcost && tcost[arr[j].nID-1]!= 0) {

nmixcost = tcost[arr[j].nID-1];

nidtemp =
arr[j].nID;

}

}

if(nmixcost== INFINITE) {//除起始顶点外的所有节点都已经被处理完毕,退出

break;

}

pbegin->pmincost[nidtemp-1] = nmixcost;

ptemp =
arr[nidtemp-1].pVer;//重新设定当前顶点

pbDone[nidtemp-1] = 1;//表示当前顶点已经被处理过了,其路径已经最短,代价最小

}

}

free(pbDone);

free(tcost);

return TRUE;

}

/**********************************************************

*函数名:MinRoute

*参数:arr-图的数组;nSrID-起始节点序号;nDsID-目的节点序号

*返回值:无

*说明:给定图的数组,利用Dijkstra函数处理之后,根据设定的起始和终止节点序号,打印

*最短路径和最小代价。

***********************************************************/

void MinRoute(nodearr[],UINTnSrID,
UINT
nDsID)

{

if(nSrID<0||
nSrID>g_node_num || nDsID<0||nDsID>g_node_num) {

printf("Invalid node number!\n");

}

intnid;

vertex*ptemp = arr[nSrID-1].pVer;

printf("thetotal cost is: %d\n", ptemp->pmincost[nDsID-1]);

printf("thepath is:");

nid =
nDsID;

printf("%d->",arr[nid-1].nID);

while(ptemp->next[nid-1]->id!= arr[nSrID-1].nID){

nid =ptemp->next[nid-1]->id;//回溯路径

printf("%d->",nid);

}

printf("%d\n",arr[nSrID-1]);

}

/*****************************************

*函数名:UnitGraphic

*参数:arr-图的数组

*返回值:无

*说明:释放内存

*****************************************/

void UnitGraphic(nodearr[])

{

UINTi;

for(i=0;i<g_node_num; i++) {

if(arr[i].pVer!=
NULL) {

SAFEFREE(arr[i].pVer->next);

SAFEFREE(arr[i].pVer->pmincost);

}

}

}

int main(intargc,
char *argv[])

{

charfilepath[MAX_STRLEN];//图的信息文件

nodegraphic[MAX_VERTEX_NUM] = {0};//图的数组

intsid, did;

intselnum;

if(argc< 2) {

printf("usage:*.exe input\n");

exit(1);

}

strcpy(filepath,
argv[1]);

/***********初始化图***************/

if(!InitGraphic(filepath,graphic,
MAX_VERTEX_NUM)) {

UnitGraphic(graphic);

exit(1);

}

printf("****  Print The Graphic information  ****");

ViewGraphic(graphic);//打印图

/************dijkstra运算***********/

if(!Dijkstra(graphic)){

UnitGraphic(graphic);

exit(1);

}

printf("\n****Findthe shortest path between nodes****");

printf("\n1.Viewminimum route between nodes.");

printf("\n2.Exit.");

for(;;){

printf("\nEnter Your Selection:");

scanf("%d",&selnum);

switch(selnum)    {

case1:    {

printf("\nEnter source node ID:");

scanf("%d",&sid);

printf("\nEnter destination node ID:");

scanf("%d",&did);

MinRoute(graphic, sid, did);//打印最优路径

break;

}

case 2:

exit(1);

default:{

printf("\nEnter proper choice.\n");

break;

}

}

}

UnitGraphic(graphic);

return0;

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 21:37:35

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法的相关文章

[C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)

1 Dijkstra算法 1.1 算法基本信息 解决问题/提出背景 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径) 算法思想 贪心算法 按路径长度递增的次序,依次产生最短路径的算法 [适用范围]Dijkstra算法仅适用于[权重为正]的图模型中 时间复杂度 O(n^3) 补充说明 亦可应用于[多源最短路径](推荐:Floyd算法(动态规划,O(n^3))) Dijkstra 时间复杂度:O(n^3) 1.2 算法描述 1.2.1 求解过程(具体思路) 1.2.2 示例 1.2

数据结构之单源最短路径(迪杰斯特拉算法)-(九)

最开始接触最短路径是在数据结构中图的那个章节中.运用到实际中就是我在大三参加的一次美赛中,解决中国的水资源问题.所谓单源最短路径,就是一个起点到图中其他节点的最短路径,这是一个贪心算法. 迪杰斯特拉算法原理(百科): 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的集合(初始时只含有源点V0) (2)V-S=T:尚未确定的顶点集合 将T中顶点按递增的次序加入到S中,保证: (1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度 (2)每个顶

迪杰斯特拉(Dijkstra)算法求最短路径

我用的是邻接矩阵来存储图的. 代码如下: void Graph:: Dijkstra(){ struct DijNode{ int index; int distance; vector<string> path; bool Founded; //判定是否找到了... }; DijNode*shorestPaths=new DijNode[mgraph.vexnum]; string startPoint; int startIndex; cout<<"请输入单源点:&q

数据结构之最短路径(1) [迪杰斯特拉算法]

迪杰斯特拉算法介绍: 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想: 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离). 初始时,S中只有起点s:U中是除s之外的顶点,并且

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法 本篇名言:"希望是厄运的忠实的姐妹. --普希金" 我们继续来看下数据结构图中的一个算法,这个算法来自图灵奖得主. 1.  Floyd算法介绍 Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名.注意这个可不是心理学的那个弗洛伊德. 是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径

42. 蛤蟆的数据结构笔记之四十二图的遍历之广度优先

42. 蛤蟆的数据结构笔记之四十二图的遍历之广度优先 本篇名言:"生活真象这杯浓酒 ,不经三番五次的提炼呵 , 就不会这样一来可口 ! -- 郭小川" 继续看下广度优先的遍历,上篇我们看了深度遍历是每次一个节点的链表是走到底的. 欢迎转载,转载请标明出处:http://write.blog.csdn.net/postedit/47029275 1.  原理 首先,从图的某个顶点v0出发,访问了v0之后,依次访问与v0相邻的未被访问的顶点,然后分别从这些顶点出发,广度优先遍历,直至所有的

48. 蛤蟆的数据结构笔记之四十八的有向无环图的应用关键路径

48. 蛤蟆的数据结构笔记之四十八的有向无环图的应用关键路径 本篇名言:"富贵不淫贫贱乐 ,男儿到此是豪雄.-- 程颢" 这次来看下有向无环图的另一个应用关键路径. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47135061 1.  关键路径 与AOV-网相对应的是AOE-网(Activity On Edge)即边表示活动的网.AOE-网是一个带权的有向无环图,其中,顶点表示事件(Event),弧表示活动,权表

49. 蛤蟆的数据结构笔记之四十九图的连通性问题

49. 蛤蟆的数据结构笔记之四十九图的连通性问题 本篇名言:"我们不得不饮食.睡眠.游惰.恋爱,也就是说,我们不得不接触生活中最甜蜜的事情:不过我们必须不屈服于这些事物 .....--约里奥?居里"     此篇就作为数据结构入门笔记的最后一篇吧. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47135259 设图G=(V,E)是一个无向图,G的一个连通分支是一个最大的连通子图,即一个连通分支是不包含在任何更大的

46. 蛤蟆的数据结构笔记之四十六普里姆算法

46. 蛤蟆的数据结构笔记之四十六普里姆算法 本篇名言:"手莫伸 ,伸手必被捉.党与人民在监督 ,万目睽睽难逃脱.汝言惧捉手不伸 ,他道不伸能自觉 , 其实想伸不敢伸 ,人民咫尺手自缩.-- 陈毅" 连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边.所谓的最小成本,就是n个顶点,用n-1条边把一个连通图连接起来,并且使得权值的和最小.构造连通网的最小代价生成树,即最小生成树(Minimum Cost Spanning Tree). 找连通图的最