图
1.学习总结
1.1图的思维导图
1.2 图结构学习体会
图(graph):是一种较线性表和树更为复杂的数据结构,图形结构中,结点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关
线性表:数据元素之间仅有线性关系,每个数据元素只有一个直接前驱和一个直接后继
树:树形结构中,数据元素之间有着明显的层次关系,并且每一层上的数据元素可能和下一层中多个元素(即其孩子结点)相关,但只能和上一层中一个元素(即其双亲结点)相关
- 深度遍历算法:将一个子节点的所有内容全部遍历完后再遍历其他节点
- 广度遍历算法:分层次进行遍历
- Prim和Kruscal算法:在加权连通图里搜索最小生成树,代码量较少
- Dijkstra算法:以起始点为中心向外扩展直到扩展到终点为止,最后得到一个最短路径
- 拓扑排序算法:有向图,不唯一,必须判断有无环路
2.PTA实验作业
题目1: 图着色问题
1.设计思路
用图的遍历解题,遍历的时候判断颜色是否相同即可。
便利过程中应注意需要不同颜色的个数等于k。
2.代码截图
![](https://images2018.cnblogs.com/blog/1284894/201806/1284894-20180618143718140-2108153722.png)
![](https://images2018.cnblogs.com/blog/1284894/201806/1284894-20180618143726697-818053348.png)
3. PTA提交列表说明
题目2.公路村村通
1.设计思路
求最小生成树的问题,给出城镇和城镇之间的费用作为权重,求出要连通所有城镇的最少费用,也就是求出这个图的最小生成树,当然不能连通时输出-1
是先用邻接矩阵的方法存储图,然后就运用Prim算法求出这个图的最小生成树,最后输出最少费用dist
2.代码截图
3.pta提交列表
3.题目:城市间紧急救援
1.设计思路
基于dijkstra算法的问题。 要考虑最优路径上的点权和尽可能大,所以出现两路径长度相等时要进行关于点权和的判断。
另外还要记录最短路径的条数,只需开一个数组记载,每次更新时基于上一点的最短路径条数更新即可。每次更新最优路径时,将上一点记录在theway数组,用于最后输出最优路径。
2.代码截图
3.pta提交列表
3.截图本周题目集的PTA最后排名
4. 阅读代码
7-3 六度空间
- #include<stdio.h>
- #include<malloc.h>
- #define MAX 10001//最大顶点数
- /**
- *解题思想:
- *对图进行广度搜索
- *得出每层中的顶点数
- *计算百分比
- */
- int BFS(int i, int N, int ** snap)
- {// 队列 遍历登记 队头 队尾 计数器 层数
- int q[MAX], visit[MAX], front, rear, count, level, last, tail, v, j;
- for (j = 0; j < 10001; j++)//初始化数组
- visit[j] = 0;
- visit[i] = 1;//开始结点
- front = rear = -1;//队列初始化
- count = 1;//计算六度空间的个数
- level = 0;//level计算层数,等于6时跳出
- last = i;//last为上一层最后的顶点
- q[++rear] = i;//入队 当前顶点所在层数
- while (front<rear) //遍历队列(六层以内)
- {
- /*
- *图的广度搜索原理解析:
- *类似二叉树的层序遍历
- *1、从所需要的顶点进入图(类似利用此顶点为树的根结点,构建一棵树)
- *2、根结点入队列
- *3、寻找与此顶点相连的所有顶点并放入队列中(图的临接矩阵中,储存的是每个顶点间的边的关系,而且无向图的临接矩阵一定为对称矩阵)
- *4、当顶点所在行遍历结束,取出队列的下一个顶点,重复。直至遍历所有的顶点
- */
- v = q[++front]; //出队
- for (j = 1; j <= N; j++)//遍历
- if (!visit[j] && snap[v][j] == 1)
- {//当结点没有记录而且此处结点为顶点时
- q[++rear] = j;//入队列
- visit[j] = 1;//记录对应位置
- count++;//计数器
- tail = j;//tail是当前层的最后一个顶点
- }
- if (v == last)
- {
- level++;//层数加一
- last = tail;//记录最后一个顶点
- }
- if (6 == level)//等于六层时,退出循环
- break;
- }
- return count;//返回六度空间内所有顶点数
- }
- int main(void)
- {
- int N, M;
- int count = 0;
- scanf("%d %d", &N, &M);
- int **snap;//实现动态分配二维数组
- /*注意:
- *******动态分配必须按照顺序分配
- *******同时数组释放内存的时候要按照先后顺序释放
- *******否则会出现野指针
- *******内存泄漏导致程序崩溃
- */
- snap = (int**)malloc(sizeof(int*) * (N + 1));
- if (snap == NULL)
- return -1;
- //动态分配内存存在失败的可能,所以
- //在进行动态分配内存后
- //应该进行对应的指针是否为空指针的判断
- int i, x, y, j;
- for (i = 0; i <= N; i++)
- {
- *(snap + i) = (int *)malloc(sizeof(int) * (N + 1));
- if (*(snap + i) == NULL)
- return -1;
- }
- for (i = 0; i < M; i++)
- {
- scanf("%d %d", &x, &y);//无向图对角线对称
- snap[x][y] = snap[y][x] = 1;//关系对等
- }
- for (i = 1; i <= N; i++)
- {
- count = BFS(i, N, snap);
- printf("%d: %.2f%%\n", i, (float)count / N * 100);
- }
- //直接进行头指针的内存释放不全等于所有指针内存的释放
- //free(snap);
- for (i = 0; i < N; i++)
- {
- free(*(snap + i));
- *(snap + i) = NULL;
- }
- free(snap);
- snap = NULL;
- return 0;
- }