前言:
本系列是笔者暑假自学数据结构的笔记整理而来,共126页,3w+字。现在正式开学上课,补充老师所讲内容,并且仔细勘误,根据老师的教学进度分章节发布在CSDN上。

教材使用的是王红梅等所著的数据结构——从概念到C++实现(第三版)。
暑假自学时期主要参考的网课:
青岛大学-王卓
武汉大学-李春葆

隔了好久,补发。

目录

  • 定义与概念
  • 图的存储结构
  • 图的遍历
  • 生成树
  • 最小生成树
  • 最短路径
  • AOE网和关键路径

定义与概念






图的存储结构


/*图的基本运算InitGraph(&g):图初始化ClearGraph(&g):销毁图DFS(G, V):从顶点v出发深度优先遍历BFS(G, v):从顶点v出发广度优先遍历
*/#define MAXV 100//最大顶点个数
#define InfoType int
typedef struct
{int no;//顶点编号InfoType info;//顶点其他信息
}VertexType;typedef struct //图的定义
{int edge[MAXV][MAXV];//邻接矩阵int n, e;//顶点数边数VertexType vexs[MAXV];//存放顶点信息
}MGraph;


//图的邻接表存储类型定义如下:
typedef struct ANode
{int adjvect;//该边的终点编号struct ANode *nextare;//指向下一条边的指针InfoType info;//该边的权值等信息
}ArcNode;typedef struct Vnode
{VertexType data;//顶点信息ArcNode *firstarc;//指向第一条便
}VNode;typedef struct
{VNode adjlist[MAXV];//邻接表int n, e;//图中顶点数n和边数e
}ALGraph;


图的遍历

//DFS,时间复杂度O(n+e)
void DFS(ALGraph *G, int v)
{ArcNode *p;int w;int visited[MAXV];visited[v] = 1;//用visited数组表示节点是否被访问过cout << v;//输出被访问顶点的编号p = G->adjlist[v].firstarc;//p指向顶点v的第一条边的边头节点while (p != nullptr){w = p->adjvect;if (visited[w] == 0){DFS(G, w);//若w顶点未访问,递归访问它}p = p->nextare;//p指向顶点v的下一条边的边头节点}
}


//BFS,时间复杂度为O(n+e)
void BFS(ALGraph *G, int v)
{ArcNode *p;int w, i;int queue[MAXV], front = 0, rear = 0;//定义循环队列int visited[MAXV];for (int i = 0; i < G->n; i++){visited[i] = 0;//访问标志数组初始化}cout << v;//输出被访问顶点的编号visited[v] = 1;//置已被访问顶点的编号rear = (rear + 1)%MAXV;queue[rear] = v;//v进队while (front != rear)//队列不空{front = (front + 1)%MAXV;w = queue[front];//出队并赋给wp = G->adjlist[w].firstarc;//找w的第一个邻接点while (p != nullptr){if (visited[p->adjvect] == 0){cout << p->adjvect;//访问之visited[p->adjvect] = 1;rear = (rear + 1)%MAXV;//相邻顶点进队queue[rear] = p->adjvect;}p = p->nextare;//找下一个邻接顶点}}
}




void DFS1(ALGraph *G)
{int i;for (int i = 0; i < G->n; i++){if (visited[i] == 0){DFS(G, i);}}
}

void BFS1(ALGraph *G)
{int i;for (int i = 0; i < G->n; i++){if (visited[i] == 0){BFS(G, i)}}
}

int visited[MAXV];
bool Connect(ALGraph *G)//判断无向图G的连通性
{int i;bool flag = true;for (int i = 0; i < G->n; i++){visited[i] = 0;//visited[]数组置初值}DFS(G, 0);//从顶点0开始深度优先遍历for (int i = 0; i < G->n; i++){if (visited[i] == 0){flag = false;break;}}return flag;
}

void ExistPath(ALGraph *G, int u, int v, bool &has)
{//has表示u到v是否有路径int w;ArcNode *p;visited[u] = 1;//置已访问标记if (u == v)//找到一条路径{has = true;//置has为true并结束算法return;}p = G->adjlist[u].firstarc;//p指向顶点u的第一个相邻点while (p != nullptr){w = p->adjvect;//w为顶点u的相邻顶点if (visited[w] == 0)//若w顶点未访问,递归访问它{ExistPath(G, w, v, has);}p = p->nextare;//p指向顶点u的下一个相邻点}
}

void FindaPath(ALGraph *G, int u, int v, int path[], int d)
{//d表示path中的路径长度,初值为-1int w, i;ArcNode *p;visited[u] = 1;d++;//路径长度d增1,顶点u加入到路径中path[d] = u;if (u == v)//找到一条路径后输出并返回{cout << "一条简单路径为:";for (int i = 0; i <= d; i++){cout << path[i];}cout << '\n';return;//找到一条路径后返回}p = G->adjlist[u].firstarc;//p指向顶点u的第一个相邻点while (p != nullptr){w = p->adjvect;//相邻点的编号为wif (visited[w] == 0){FindaPath(G, w, v, path, d);}p = p->nextare;//p指向顶点u的下一个相邻点}
}

void PathAll(ALGraph *G, int u, int v, int l, int path[], int d)
{//d是到当前为止已走过的路径长度,调用时初值为-1int w, i;ArcNode *p;visited[u] = 1;//路径长度增1d++;path[d] = u;//将当前顶点添加到路径中if (u == v && d==l)//输出一条路径{for (int i = 0; i <= d; i++){cout << path[i] << '\n';}}p = G->adjlist[u].firstarc;//p指向u的第一条边的边头节点while (p != nullptr){w = p->adjvect;//w为u的邻接顶点if (visited[w] == 0)//若顶点未标记访问,则递归访问之{PathAll(G, w, v, l, path, d)}p = p->nextare;//找u的下一个邻接顶点}visited[u] = 0; //恢复环境,使该顶点可重新使用
}

typedef struct
{int data;//顶点编号int parent;//前一个顶点的位置
}Quere;void ShortPath(ALGraph *G, int u, int v)
{//输出从顶点u到顶点v的最短逆路径ArcNode *p;int w, i;Quere qu[MAXV];//定义非循环队列int front = -1, rear = -1;//队列的头、尾指针int visited[MAXV];for (int i = 0; i < G->n; i++)//访问标记置初值0{visited[i] = 0;}rear++;//顶点u进队qu[rear].data = u;qu[rear].parent = -1;visited[u] = 1;while (front != rear)//队不空时循环{front++;//出队顶点ww = qu[front].data;if (w == v)//输出逆路径{i = front;while (qu[i].parent != -1){cout << qu[i].data;i = qu[i].parent;}cout << qu[i].data;break;}p = G->adjlist[w].firstarc;//找w的第一个邻接点while (p != nullptr){if (visited[p->adjvect] == 0){visited[p->adjvect] = 1;rear++;//将w的未访问过的邻接点进队qu[rear].data = p->adjvect;qu[rear].parent = front;}p = p->nextare;//找w的下一个邻接点}}
}

生成树

最小生成树


#define INF 32767
void Prim(MGraph g, int v)
{int lowcost[MAXV];int min;int closet[MAXV], i, j, k;for (int i = 0; i < g.n; i++){lowcost[i] = g.edge[v][i];closet[i] = v;}for (int i = 1; i < g.n; i++){min = INF;for (int j = 0; j < g.n; j++){if (lowcast[j] != 0 && lowcost[j] < min){min = lowcost[j];k = j;}}cout << closet[k] << k << min;lowcast[k] = 0;for (int j = 0; j < g.n; j++){if (lowcast[j] != 0 && g.edges[k][j] < lowcast[j]){lowcost[j] = g.edge[k][j];closet[j] = k;}}}
}


typedef struct
{int u;//边的起始顶点int v;//边的终止顶点int w;//边的权值
}Edge;void Kruskal(MGraph g)
{int i, j, u1, v1, sn1, sn2, k;int vset[MAXV];Edge E[MAXV];//存放所在边k = 0;//E数组的下标从0开始计for (int i = 0; i < g.n; i++)//由g产生的边集E{for (int j = 0; j < g.n; j++){if (g.edge[i][j] != 0 && g.edge[i][j] != INF){E[k].u = i;E[k].v = j;E[k].w = g.edge[i][j];k++;}}}InsertSort(E, g, e);//用直接插入排序对E数组按权值递增排序for (int i = 0; i < g.n; i++)//初始化辅助数组{vset[i] = i;k = 1;//k表示当前构造生成树的第几条边j = 0;//E中边的下标,初值为0while (k < g.n)//生成的边数小于n时循环{u1 = E[j].u;//取一条边的头尾顶点v1 = E[j].v;sn1 = vset[u1];sn2 = vset[v1];//分别得到两个顶点所属的集合编号if (sn1 != sn2)//两顶点属于不同的集合{cout << u1 << v1 << E[j].w;k++;//生成边数增1for (int i = 0; i < g.n; i++)//两个集合统一编号{if (vset[i] == sn2)//集合编号为sn2的改为sn1{vset[i] = sn1;}}}j++;//扫描下一条边}}
}

最短路径

void Dijkstra(MGraph g, int v)
{int dist[MAXV], path[MAXV];int s[MAXV];int mindis, i, j, u;for (int i = 0; i < g.n; i++){dist[i] = g.edge[v][i];//距离初始化s[i] = 0;//s[]置空if (g.edge[v][i] < INF)//路径初始化{path[i] = v;//顶点v到i有边时}else{path[i] = -1;//顶点v到i没边时}}s[v] = 1;//源点v放入s中for (int i = 0; i < g.n; i++)//循环n-1次{mindis = INF;for (int j = 0; j < g.n; j++){if (s[j] == 0 && dist[j] < mindis){u = j;mindis = dist[j];}}s[u] = 1;//顶点u放入s中for (int j = 0; j < g.n; j++)//修改不在s中的顶点的距离{if (s[j] == 0){if (g.edge[u][j] < INF && dist[u] + g.edge[u][j] < dist[j]){dist[j] = dist[u] + g.edge[u][j];path[j] = u;}}}}Dispath(dist, path, s, g.n, v);//输出最短路径
}





void Floyd(MGraph g)//求每对顶点之间的最短路径
{int A[MAXV][MAXV];//建立数组Aint path[MAXV][MAXV];//建立path数组int i, j, k;for (int i = 0; i < g.n; i++){for (int j = 0; j < g.n; j++){A[i][j] = g.edge[i][j];if (i != j && g.edge[i][j] < INF){path[i][j] = i;//i和j顶点之间有一条边时}else{path[i][j] = -1;//i和j顶点之间没有一条边时}}}for(k = 0; k < g.n; k++)//求Ak[i][j]{for(i = 0; i < g.n; i++){for(j = 0; j < g.n; j++){if (A[i][j] > A[i][k] + A[i][j])//找到更短路径{A[i][j] = A[i][k] + A[i][j];//修改路径长度path[i][j] = path[k][j];//修改最短路径为经过顶点k}}}}
}

typedef struct//表头节点类型
{VertexType data;//顶点信息int count;//存放顶点入度ArcNode *firstarc;//指向第一条边
}VNode;
void TopSort(Vnode adj[], int n)
{int i, j;int St[MAXV], top = -1;//栈的指针为topArcNode *p;for (int i = 0; i < n; i++){if (adj[i].count == 0)//入度为0的顶点进栈{top++;St[top] = i;}}while (top > -1)//栈不空时循环{i = St[top];//出栈top--;cout << i;p = adj[i].firstarc;while (p != nullptr){j = p->adjvect;adj[j].count--;if (adj[j].count == 0){top++;St[top] = j;}p = p->nextare;//找下一个相邻顶点}}
}

AOE网和关键路径





以上 如果此篇博客对您有帮助欢迎点赞与转发 有疑问请留言或私信 2021/1/12

【数据结构】第六章——图(详解)相关推荐

  1. 数据结构第六章——图

    数据结构第六章--图 图的定义和术语 G = (V, E) V:顶点(数据元素的)有穷非空集合: E:边的有穷集合. 无向图:每条边都是无方向的. 有向图:每条边都是有方向的. 完全图:任意两个顶点都 ...

  2. 大学物理第六章 静电场详解(全)

    电场 电场强度 一.电荷 电荷的概念是从物体带电的现象中产生的,电荷是物体状态的一种属性,宏观物体或微观粒子处于带电状态就说它们带有电荷 物体或微观粒子所带的电荷有两种,称为正电荷和负电荷,带同种电荷 ...

  3. 王道408数据结构——第六章 图

    文章目录 一.图的基本概念 二.图的储存 邻接矩阵 邻接表 十字链表 邻接多重表 三.图的基本操作 四.图的遍历 广度优先搜索(BFS) 深度优先搜索(DFS) 图的遍历和图的连通性 五.最小生成树 ...

  4. (王道408考研数据结构)第六章图-第四节4:最短路径之迪杰斯特拉算法(思想、代码、演示、答题规范)

    文章目录 一:BFS算法局限性 二:迪杰斯特拉(dijkstra)算法基本思想 三:迪杰斯特拉(dijkstra)算法代码实现 四:迪杰斯特拉(dijkstra)算法代码视频演示 五:迪杰斯特拉(di ...

  5. (王道408考研数据结构)第六章图-第四节1:最小生成树之普利姆算法(思想、代码、演示、答题规范)

    文章目录 一:普利姆(Prim)算法算法思想 二:普利姆(Prim)算法注意点 三:普利姆(Prim)算法代码实现 四:普利姆(Prim)算法代码视频演示 五:普利姆(Prim)算法动画演示 六:普利 ...

  6. (王道408考研数据结构)第六章图-第四节5:最短路径之弗洛伊德算法(思想、代码、演示、答题规范)

    文章目录 一:动态规划基本思想 二:弗洛伊德(Floyd)算法基本思想 三:弗洛伊德(Floyd)算法代码实现 四:弗洛伊德(Floyd)算法代码视频演示 五:弗洛伊德(Floyd)算法代码答题规范 ...

  7. (王道408考研数据结构)第六章图-第四节3:最短路径之BFS算法(思想、代码、演示、答题规范)

    文章目录 一:BFS算法基本思想 二:BFS算法代码 三:反思 最短路径shortestpath):主要有以下两类最短路径问题 单源最短路径问题:一个顶点到其他顶点最短路径 迪杰斯特拉算法(dijks ...

  8. (王道408考研数据结构)第六章图-第四节2:最小生成树之克鲁斯卡尔算法(思想、代码、演示、答题规范)

    文章目录 一:克鲁斯卡尔(Kruskal)算法思想 二:克鲁斯卡尔(Kruskal)算法代码实现 三:克鲁斯卡尔(Kruskal)算法视频演示 四:克鲁斯卡尔(Kruskal)算法动画演示 五:克鲁斯 ...

  9. (王道408考研数据结构)第六章图-第三节:图的遍历(DFS和BFS)

    文章目录 一:图的深度优先遍历(DFS) (1)回溯算法和DFS A:回溯算法的本质 B:回溯算法的框架 C:全排列 (2)图的DFS A:DFS思想 B:动画演示 C:代码 二:图的广度优先遍历(B ...

  10. (王道408考研数据结构)第六章图-第二节1:图的存储结构(邻接矩阵、邻接表、十字链表和邻接多重表)

    文章目录 一:邻接矩阵--适合存储稠密图 (1)邻接矩阵定义 (2)代码 二:邻接表 (1)邻接表定义 (2)代码 (3)邻接表和邻接矩阵对比 三:十字链表(用于有向图) 四:邻接多重表(用于优化无向 ...

最新文章

  1. C# MoreLinq 扩展安装
  2. sshd系统自带启动脚本详解
  3. GitHub上值得关注的iOS开源项目
  4. 第五章 PX4-Pixhawk-GPS解析
  5. 把Liststring集合,编程string,并以“,”号分割
  6. Java架构师必看的10本书
  7. 人用药品注册技术规定国际协调会议(ICH)
  8. Exchange 2010输入序列号方式
  9. 清爽通用工作总结汇报ppt模板免费下载_PPTX图片设计素材_包图网888pic.com
  10. 干货 | 人工智能应用落地的关键成功要素
  11. 前端开发工程师,CSS盒子模型居中方法
  12. 当Linux配置zh_CN.UTF-8 ,中文还是显示乱码解决办法
  13. 银行卡所属银行的查询接口--阿里提供
  14. elasticsearch从入门到入门系列(二)---快速入门A
  15. 如何使用 Docker 部署一个私有化的为知笔记
  16. 网络安全专业的就业方向有哪些?
  17. matlab交叉耦合,交叉耦合滤波器怎么从耦合矩阵得出频率响应
  18. linux 磁盘压测工具 fps,荣耀MagicBook Pro锐龙版性能评测,可媲美MX150 2GB核心显卡...
  19. Android 网络编程(二) HTTP协议解析
  20. python猴子偷桃 #题目:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第

热门文章

  1. 免费在线图片识别文字工具
  2. HTTPS/数字证书/数字签名
  3. 前端面试技巧和注意事项
  4. java环境变量配置 JDK环境变量
  5. 用Python分析了7w+《悬崖之上》影评,看看观众都是怎么说?
  6. python给女朋友_Python 给女朋友道歉的一天
  7. Arduino ESP8266/ESP32读取和改写MAC
  8. 【联邦学习】横向联邦学习(Horizontal Federated Learning,HFL)
  9. 剖析Spring源码:加载IOC容器
  10. 单片机---1.仿真实现跑马灯(从左往右,在从右往左)