上一篇主要讲了二叉树的先序,中序,后序遍历算法以及深度和节点的算法,这篇就讲一讲图的基本算法。

一、图的基本概念

1.1有向图G1:

有向图G是由两个集合V(G)和E(G)组成的,其中:V(G)是顶点的非空有限集,E(G)是有向边(也称弧)的有限集合,弧是顶点的有序对,记为<v,w>,v,w是顶点,v为弧尾,w为弧头,(v,w)!=(w,v)。

1.2无向图G2:

无向图G是由两个集合V(G)和E(G)组成的,其中:V(G)是顶点的非空有限集,E(G)是边的有限集合,边是顶点的无序对,记为(v,w)或(w,v),并且(v,w)=(w,v)。

二、图的存储结构(以无向图G1为例)

2.1邻接矩阵(关联矩阵、关系矩阵)

特点:由上述可知,无向图或网络的邻接矩阵是对称的。并且,该法比较简单,用一个二维数组就可存储。
缺点:浪费空间,可用处理“稀疏”矩阵的方式去处理。

2.2邻接表G1

邻接表是图的一种链式存储结构。在邻接表中,对图中的每个结点建立一个单链表。第i个单链表中的结点表示依附于顶点Vi的边(有向图中指以Vi为尾的弧). 
在边少的情况下,用邻接表比邻接矩阵节省存储空间。

三、图的遍历

3.1深度优先遍历

从图的某一顶点V0出发,访问此顶点;然后依次从V0的未被访问的邻接点出发,深度优先遍历图,直至图中所有和V0相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未被访问的顶点作起点,重复上述过程,直至图中所有顶点都被访问为止。
上图遍历结果为:V1 --> V2 --> V4 --> V8 --> V5 --> V3 --> V6 --> V7

3.2广度优先遍历

从图的某一顶点V0出发,访问此顶点后,依次访问V0的各个未曾访问过的邻接点;然后分别从这些邻接点出发,广度优先遍历图,直至图中所有已被访问的顶点的邻接点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未被访问的顶点作起点,重复上述过程,直至图中所有顶点都被访问为止。
上图遍历结果为:V1 --> V2 --> V3 --> V4 --> V5 --> V6 --> V7 --> V8

四、迪杰斯特拉算法求单源最短路径(Dijkstra)

算法描述;
1)设A[1..n,1..n]为有向图的带权邻接矩阵,A[i,j]表示弧(Vi,Vj)上的权值,若(Vi,Vj)不存在,则A[i,j]为无穷大;S 为已找到从源点V0出发的最短路径的终点集合,初始状态为{V0};DIST[1..n]为个终点当前找到的最短路径长度,初始值为DIST[i]=A[V0,i];
2)选择u,使DIST[u]=min{DIST[w]|w!∈S,w∈V}, S=S∪{u},其中,V为有向图的顶点集合;
3)对于所有不在S中终点w,若 DIST[u]+A[u,w] < DIST[w], 则修改DIST[w]为 DIST[w]=DIST[u]+A[u,w];
4)重复操作2)、3)共n-1次,由此可求得从V0到各终点的最短路径。

五、代码分析

把基本概念讲解后,我们来看看代码的实现,注释都比较清楚,我就不一一讲解了
#include <stdio.h>
#include <malloc.h>
#define MAX 1000//表示两顶点间无连接
#define VN 5//顶点数
typedef struct GLink GLink;
/*
初始化邻接矩阵(图)
*/
int G[VN][VN] = {0,9,6,3,MAX,9,0,4,5,MAX,6,4,0,MAX,7,3,5,MAX,0,8,MAX,MAX,7,8,MAX};
/*
邻接表的node
*/
struct GLink{int adjvex;//下标int weight;//权值GLink *next;//邻接表node的下一个顶点
};
GLink *GL[VN];/*存储所有的顶点*/
int visit[VN];/*存储已经遍历的顶点*//*
将上面的邻接矩阵转化为邻接表
*/
void createGLink(int G[VN][VN]){int i,j;GLink *q,*p;for(i = 0;i<VN;i++){GL[i] = q =NULL;for(j = 0;j < VN ;j++){if((i != j) && ( G[i][j] > 0) && (G[i][j] < MAX)){  //存在有效路径p = (GLink * ) malloc(sizeof( GLink));p->adjvex = j;/*获取顶点的下标*/    p->weight = G[i][j];/*获取顶点的权值*/if(NULL==GL[i])GL[i] = p;elseq->next = p;q = p;}}q->next = NULL;}
}
/*
深度遍历优先
*/
void DFS(GLink *G[VN],int v){GLink *p;p = G[v];printf("[ %d ]  ",(v+1));visit[v] = 1;while(NULL != p){//printf("第 %d 个顶点 到第 %d 个顶点的权值为: %d \n",(v+1),(p->adjvex + 1),p->weight);if ((visit[p->adjvex] != 1)){DFS(G,p->adjvex);}p = p->next;}//printf(" 第 %d 个顶点完成遍历\n ",(v+1));
}
/*
广度遍历优先
*/
void BFS(GLink *G[VN],int v){int i,n = 0;//n 是获取队列中的顶点GLink *p;int Q[VN];//存放已经访问过的顶点//初始化队列for(i = 0;i < VN;i++){Q[i] = MAX;}visit[v] = 1;Q[0] = v;int k = 1;//当前队列中的顶点数printf("[ %d ]  ",(v+1));while((k<VN) && (n<i)){p = G[Q[n]];//找到当前顶点边表链表头指针n++;while(NULL != p){//printf("第 %d 个顶点 到第 %d 个顶点的权值为: %d \n",(v+1),(p->adjvex + 1),p->weight);if(visit[p->adjvex] != 1){printf("[ %d ]  ",(p->adjvex+1));//将访问过的顶点入队Q[k] = p->adjvex; //修改为访问过visit[p->adjvex] = 1;k++;}p = p->next;}}
}
/*
根据Dijkstra算法求出单元最短路径   v是起始点
*/
void Short(int G[VN][VN],int v){int Dist[VN];//两点之间的最短距离int Path[VN];//存储的路径int final[VN];//已经找到的最短路径顶点int i ,j ;//外部和内部循环/*存储v顶点到其他顶点之间的距离,默认为这两点之间的最短距离*/for(i = 0; i < VN ; i++){final[i] = 0;//将final初始化,表示没有一个顶点找到了最短路径Dist[i] = G[v][i];//存储距离if(Dist[i] < MAX)Path[i] = v;//v点到i点的路径有效,存储该路径v}final[v] = 1;//标记为最短路径int min,k;for(i = 0;i < VN;i++){min = MAX;//获取最短路径k = v;//获取距离v点最短的顶点for(j = 0;j < VN ; j++){//v -> i 如果存在有效路径,并且小于当前的最小距离if( (final[i] != 1) && (Dist[i] < min) &&(Dist[i] != 0 )){k = i;min = Dist[i];}}final[k] = 1;//k点离v点最近,将k 点保存在final中/*在v点到j点路径上,如果存在该点k ,使得v->k->j的距离小于v->j 的距离*/for(j = 0;j < VN ; j++){if((final[j] != 1) && (Dist[k] + G[k][j] < Dist[j] )){Dist[j] = Dist[k] + G[k][j];Path[j] = k;//存储该k点}}}/*打印出v点到其他顶点的最短路径及距离*/for(i = 0 ;i < VN ; i++){if(final[i]!=0){k = i;while( k != v){printf(" %d <- ",k); k = Path[k];}printf(" %d ",v);printf(" \nshortPath is %d \n\n",Dist[i]);}elseprintf(" the Vertex %d no shortPah \n ",i);}
}
void main(){int i ;for(i = 0 ;i < VN;i++){GL[i] = NULL;}i =0;createGLink(G);printf("深度优先遍历\n ");DFS(GL,0);for(i = 0;i < VN ;i ++){visit[i] = 0;}printf("\n\n\n广度优先遍历\n");BFS(GL,0);printf(" \n\n\n最短路径算法\n");Short(G,1);
}

V1Þ V2ÞV3Þ V4ÞV5ÞV6ÞV7ÞV8

C语言基本数据结构之三(图的广度及深度遍历,求单源最短路径的Dijkstra算法)相关推荐

  1. 图的单源最短路径:Dijkstra算法实现

    本文介绍的是图的非负权值的单源最短路径问题.问题的提出是,对于有权图D,t提供源点v,要找到从v到其他所有点的最短路径,即单源最短路径问题,在本文中,解决这一问题,是普遍比较熟悉的Dijkstra算法 ...

  2. c语言单源最短路径问题实验报告,单源最短路径问题Dijkstra算法的c语言实现

    求单源最短路径是图论中比较基本的问题,通常的Dijkstra算法是按阶段进行的,每个节点标有处理和未处理状态的标记,设立一个数组,每个数组中第i个元素为源节点到第i个节点的最短路径(当然,该数组的初值 ...

  3. 图的单源最短路径(Dijkstra算法)

    单源最短路径问题 如果从图中某一顶点(源点)到达另一顶点(终点)的路径可能不止一条,如何找到一条路径使得沿此路径各边上的权值总和达到最小. Dijkstra算法由来 迪杰斯特拉算法(Dijkstra) ...

  4. 图的最短路径之Dijkstra求单源最短路径算法(C++)

    一个有向带权图求它的单源最短路径可以使用Dijkstra算法. 单源最短路径是指:从图中的某个顶点出发,到其余各个顶点权值最小的路径. Dijkstra算法需要用到三个辅助数组: dist[max]: ...

  5. 【2023王道数据结构】【图】通过C++实现图的BFS(广度优先遍历)算法求单源最短路径问题C、C++完整实现(可直接运行)

    ~~~笔锋至此又怎能平淡而终,故事开始便不承认普通✌✌✌ ✌ 题目及题解持续更新中 [2023王道数据结构目录]课后算法设计题C.C++代码实现完整版大全 题目: 通过C++实现图的BFS(广度优先遍 ...

  6. C/C++实现图的广度和深度遍历

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> # ...

  7. 【图】广度与深度遍历

    图的常用操作 FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号.若x没有邻接点或图中不存在x,则返回-1. NextNeighbor(G,x,y):假设图G中顶点y ...

  8. 图的单源最短路径,Floyd算法(数据结构c++)

    这个算法结构很是简单,但是理解还是有一定的困难,一开始做的时候想不明白,跟着算法自己动手画画就知道这个算法具体是怎么回事了. 时间复杂度是O(N*3) 算法有点动态规划的意思,有两个数组,一个(dis ...

  9. 数据结构最短路径例题_编程小白暑期进阶笔记45-C语言数据结构与算法最短路径和dijkstra算法...

    最短路径 算法特点: 迪科斯彻算法使用了广度优先搜索解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树.该算法常用于路由算法或者作为其他图算法的一个子模块. 算法思路: Dijks ...

最新文章

  1. SQL与NoSQL区别-授权方式
  2. ubuntu下磁道坏区的检测与修复
  3. 031 广播变量与累加器
  4. Entity Framework 学习中级篇3—存储过程(中)
  5. 谷歌新语言重写android,谷歌将推新设计语言 安卓APP用户界面将换新颜
  6. go string 去除引号_一起攻克面试难关:Go 面试每天一篇(第 71 天)
  7. Android无需权限保存文件,即使使用用户权限,也无法在外部存储上保存文件[Android]...
  8. php sql注入判断,php防止sql注入漏洞过滤函数的代码
  9. java 数字的进制转换
  10. 计算机会计内容是什么,会计电算化的主要内容是什么?
  11. 如何做一个真正牛X 的开源项目
  12. NeurIPS'21|MixSeq:从微观数据到宏观时序预测的桥梁
  13. Caffe学习1-图像识别与数据可视化
  14. 《第一行代码》第三版之我的第一行Android代码(一)
  15. Unity性能优化之物理引擎的优化(三)
  16. 【操作系统】进程管理
  17. 安庆集团-冲刺日志(第六天)
  18. 完美解决虚拟机占用硬盘越来越大、删除快照无效、菜单栏显示不全等问题
  19. Phonetic symbol 辅音 - 清辅音 -- /k/
  20. “No input file specified “问题的处理

热门文章

  1. id ajax,AJAX_ajax.js里面有内容显示效果,根据ID,ajax.js里面有内容显示效果,根 - phpStudy...
  2. 电脑账户头像怎么删掉_电脑用户账户头像在哪里更改?怎么更改?
  3. HTML怎么把文字分栏_PPT文字巨多!领导还不让删,怎么排版才高大上?
  4. 服务器系统linux怎么安装教程,CentOS 8.0.1905 linux服务器系统安装与配置图解教程...
  5. 重置表单验证 清除表单校验信息
  6. dataframe groupby_PySpark SQL——SQL和pd.DataFrame的结合体
  7. matlab中imfilter是什么意思,matlab中imfilter的用法
  8. python代码命令行tab补齐_Python在命令行下Tab键自动补全脚本
  9. 人工智能人才争抢白热化?学好数学才能C位出道
  10. Windows下MongoDB安装及创建用户名和密码