系统性去总结图论的知识点,有关于邻接矩阵等多方面知识点,有利于我巩固专业课上的知识点,也是自己认真去了解各项学习任务的进度。

图的表示,矩阵,邻接矩阵

  • 用邻接矩阵表示顶点间的相邻关系

  • 用一个顺序表来存储顶点信息
    设G=(V,E)是具有n个顶点的图,以1和0来表示是否是E(G)的边

  • 邻接表是图的一种顺序存储与链式存储结合的存储方法,类似于树的孩子链表表示法
    构造邻接表,链表的方式,理解简单,效率不高

#pragma once
#include<iostream>
using namespace std;enum GraphKind{DG,WDG,UDG,WUDG};template<typename VertexType,typename InfoType>
class ALGraph
{
public:static const int MAX_VERTEX_NUM = 20;ALGraph(int verNum, GraphKind _kind):vexnum(verNum), arcnum(0), kind(_kind){for (int i = 0; i < MAX_VERTEX_NUM; i++)//初始化vertices[i].firstarc = NULL;}void Create(){switch (kind){case DG://构造一个有向图CreateDG();break;case WDG://构造一个带权有向图CreateWDG();break;case UDG://构造一个无向图CreateUDG();break;case WUDG://构造一个带权无向图CreateWUDG();break;}}void displayGraph(){for (int i = 0; i < vexnum; i++){cout << "第" << i + 1 << "个顶点是:" << vertices[i].data<< "邻接表为:";ArcNode *arcNode = vertices[i].firstarc;while (arcNode){cout << "->" << vertices[arcNode->adjvex].data<< "(" << arcNode->info << ")";arcNode = arcNode->nextarc;}cout << endl;}}
private:void InitVertics()//初始化头列表{cout << "请输入每个顶点的关键字:" << endl;VertexType val;for (int i = 0; i < vexnum; i++){cin >> val;vertices[i].data = val;}}void insertArc(int vHead, int vTail, InfoType w){ArcNode *newArcNode = new ArcNode;newArcNode->adjvex = vTail;newArcNode->nextarc = NULL;newArcNode->info = w;ArcNode *arcNode = vertices[vHead].firstarc;if (NULL == arcNode)vertices[vHead].firstarc = newArcNode;else{while (arcNode->nextarc != NULL){arcNode = arcNode->nextarc;}arcNode->nextarc = newArcNode;}arcnum++;}//构造一个有向图void CreateDG(){InitVertics();int vhead, vtail;cout << "请依次输入每条边的开始顶点和结束顶点:" << endl;while (cin >> vhead >> vtail){insertArc(vhead, vtail, 0);}}//构造一个带权有向图void CreateWDG(){InitVertics();int vhead, vtail;InfoType w;cout << "请依次输入每条边的开始顶点和结束顶点和权值:" << endl;while (cin >> vhead >> vtail >> w){insertArc(vhead, vtail, w);}}//构造一个无向图void CreateUDG(){InitVertics();int vhead, vtail;cout << "请依次输入每条边的开始顶点和结束顶点:" << endl;while (cin >> vhead >> vtail){insertArc(vhead, vtail, 0);insertArc(vtail, vhead, 0);}}//void CreateWUDG(){InitVertics();int vhead, vtail;InfoType w;cout << "请依次输入每条边的开始顶点和结束顶点和权值:" << endl;while (cin >> vhead >> vtail>>w){insertArc(vhead, vtail, w);insertArc(vtail, vhead, w);}}struct ArcNode//表结点{int adjvex;//该弧所指向的顶点的位置ArcNode *nextarc;//指向下一条弧的指针InfoType info;//该弧相关信息的指针};struct VNode//头结点{VertexType data;//顶点信息ArcNode *firstarc;//指向第一条依附在该顶点的弧的指针};VNode vertices[MAX_VERTEX_NUM];//头列表int vexnum; //图的当前顶点数int arcnum;//图的弧数GraphKind kind;//图的种类
};//邻接表结构体

邻接矩阵

#include<iostream>
#include<vector>
using namespace std;
//枚举类型,图的种类 DG:有向图;WDG:带权值的有向图;
//UDG: 无向图;WUDG: 带权值的无向图
enum GraphKind{DG,WDG,UDG,WUDG};
template<typename VertexType,typename VRType,typename InfoType>
class MGraph
{
public:MGraph(int vexNum, GraphKind __kind) :vexnum(vexNum), arcnum(0), kind(__kind){vvec = new VertexType[vexnum];arcs = new ArcCell *[vexnum];//二维数组动态分配(vexnum*vexnum)for (int i = 0; i < vexnum; i++){arcs[i] = new ArcCell[vexnum];}}void Create(){switch (kind){case DG:CreateDG();break;case WDG:CreateWDG();break;case UDG:CreateUDG();break;case WUDG:CreateWUDG();break;default:return;}}void Init(){cout << "请输入每个顶点的关键字:" << endl;VertexType val;for (int i = 0; i < vexnum; i++){cin >> val;vvec[i] = val;}for (int i = 0; i < vexnum; i++){ArcCell ac;ac.adj = 0;ac.info = NULL;for (int j = 0; j < vexnum; j++)arcs[i][j] = ac;}}void CreateDG()//构造一个有向图{Init();int vhead, vtail;cout << "请依次输入每条边的开始顶点和结束顶点:" << endl;while (cin >> vhead >> vtail){arcnum++;arcs[vhead][vtail].adj = 1;}}void CreateWDG()//构造一个带权有向图{Init();int vhead, vtail;InfoType w;cout << "请依次输入每条边的开始顶点和结束顶点和权值:" << endl;while (cin >> vhead >> vtail >> w){arcnum++;arcs[vhead][vtail].adj = w;}}void CreateUDG()//构造一个无向图{Init();int vhead, vtail;cout << "请依次输入每条边的开始顶点和结束顶点:" << endl;while (cin >> vhead >> vtail){arcnum += 2;arcs[vhead][vtail].adj = 1;arcs[vtail][vhead].adj = 1;}}void CreateWUDG()//构造一个带权无向图{Init();int vhead, vtail;InfoType w;cout << "请依次输入每条边的开始顶点和结束顶点和权值:" << endl;while (cin >> vhead >> vtail>>w){arcnum += 2;arcs[vhead][vtail].adj = w;arcs[vtail][vhead].adj = w;}}void displayGraph(){cout << "总共有" << vexnum << "个顶点," << arcnum << "条边" << endl;for (int i = 0; i < vexnum; i++){cout << "第" << i + 1 << "个顶点是:" << vvec[i] << "相邻的边有:";for (int j = 0; j < vexnum; j++){if (arcs[i][j].adj != 0)cout << vvec[j] << "(" << arcs[i][j].adj << ")";}cout << endl;}}
private:struct ArcCell{VRType adj;//两连接点之间的权值InfoType info;};VertexType *vvec;//顶点向量ArcCell **arcs;//邻接矩阵int vexnum;//图的结点个数int arcnum;//图的边的个数GraphKind kind;//图的种类
};

dijkstra(迪杰斯特拉) 算法(利用贪心算法)

  • 解释:首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的。所谓松弛操作就是遍历一遍看通过刚刚找到的距离的最短点作为中转站会不会更近。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define Inf 0x3f3f3f3fusing namespace std;int map[1005][1005];int vis[1005],dis[1005];
int n,m;//n个点,m条边void Init ()
{memset(map,Inf,sizeof(map));for(int i=1;i<=n;i++){map[i][i]=0;}
}void Getmap()
{int u,v,w;for(int t=1;t<=m;t++){scanf("%d%d%d",&u,&v,&w);if(map[u][v]>w){map[u][v]=w;map[v][u]=w;}}  }void Dijkstra(int u)
{memset(vis,0,sizeof(vis));for(int t=1;t<=n;t++){dis[t]=map[u][t];}vis[u]=1;for(int t=1;t<n;t++){int minn=Inf,temp;for(int i=1;i<=n;i++){if(!vis[i]&&dis[i]<minn){minn=dis[i];temp=i;}}vis[temp]=1;for(int i=1;i<=n;i++){if(map[temp][i]+dis[temp]<dis[i]){dis[i]=map[temp][i]+dis[temp];}}}}int main()
{scanf("%d%d",&m,&n);Init();Getmap();Dijkstra(n);printf("%d\n",dis[1]);return 0;
}

参考文献

prim(普里姆算法)

  1. 输入:一个加权连通图,其中顶点集合为V,边集合为E;
  2. 初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
  3. 重复下列操作,直到Vnew = V:

a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);

b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
4. 输出:使用集合Vnew和Enew来描述所得到的最小生成树。
图例:


参考文献

kruskal(克鲁斯卡尔算法)

  1. 记Graph中有v个顶点,e个边

  2. 新建图Graphnew,Graphnew中拥有原图中相同的e个顶点,但没有边

  3. 将原图Graph中所有e个边按权值从小到大排序

  4. 循环:从权值最小的边开始遍历每条边 直至图Graph中所有的节点都在同一个连通分量中

             if 这条边连接的两个节点于图Graphnew中不在同一个连通分量中添加这条边到图Graphnew中
    


科鲁斯卡算法代码:主要是先排序权值,然后再选择最短的权值,禁止形成回路,判断是否两个端点是否同色

floyd(弗洛伊德算法、插点法)

  • floyd算法是解决给定的加权图中顶点间的最短路径的一种算法,是一种动态规划算法,稠密图效果最佳

参考文献

总结

  1. dijkstra(迪杰斯特拉算法) 时间复杂度O(n2),依此遍历所有方向,然后获取最短路径
  2. prim(普里姆算法) 时间复杂度O(n2),先确定一个点,然后去寻找最短路径的点,然后根据确定的点再重复去找最短的点
  3. kruskal(克鲁斯卡尔算法) 时间复杂度O(n),先确定图中权重最小的,然后再找下一个权重小的
    n-1636188111140)]
    科鲁斯卡算法代码:主要是先排序权值,然后再选择最短的权值,禁止形成回路,判断是否两个端点是否同色

floyd(弗洛伊德算法、插点法)

  • floyd算法是解决给定的加权图中顶点间的最短路径的一种算法,是一种动态规划算法,稠密图效果最佳
    [外链图片转存中…(img-jlDIyxn4-1636188111144)]

参考文献

总结

  1. dijkstra(迪杰斯特拉算法) 时间复杂度O(n2),依此遍历所有方向,然后获取最短路径
  2. prim(普里姆算法) 时间复杂度O(n2),先确定一个点,然后去寻找最短路径的点,然后根据确定的点再重复去找最短的点
  3. kruskal(克鲁斯卡尔算法) 时间复杂度O(n),先确定图中权重最小的,然后再找下一个权重小的
  4. floyd(弗洛伊德算法) 时间复杂度O(n3),分别顶点作为中介点,不断更新矩阵

图论代码大全(C++)相关推荐

  1. 《代码大全2》读后感czz

    经老师推荐,买了一本<代码大全2>,花了近3个月的时间看完了,看完后觉得还有很多值得回味的地方,而且每部分之后作者还推荐了不少经典书籍.所以,作个读书心得.全书的主题是软件构建,关于软件构 ...

  2. 与《代码大全》齐名的经典著作

    与<代码大全>齐名的经典著作 揭示微软成功的技术奥秘 C语言高手的秘籍 "本书所蕴含的思想精髓可以说是不朽的,它彻底改变了我的编程方式." --David Kline, ...

  3. javascript常用代码大全

    http://caibaojian.com/288.html     原文链接 jquery选中radio//如果之前有选中的,则把选中radio取消掉 $("#tj_cat .pro_ca ...

  4. 用python画动态樱花_利用python画一棵漂亮的樱花树,turtle画图代码大全,此处感谢知乎大佬小白...

    利用python画一棵漂亮的樱花树,turtle画图代码大全,此处感谢知乎大佬小白 此处感谢知乎大佬 小白练手 练习一下比较流行的turtle(海龟库) 画一棵漂亮的樱花树,效果如下: ps: 是动态 ...

  5. python基础代码事例-python基础代码大全

    [实例简介] python代码大全,适用于基础python学习者,里面的代码基本上是基础学习者必经过程. Python学习入门很快,但学习之路任重道远 [实例截图] [核心代码] python代码大全 ...

  6. 《代码大全2》读书笔记 Week2

    <代码大全2>第四.五章 第四章"关键的'构建'决策"主要有以下三要点:1.每种编程语言都有优点和缺点,程序员应根据需要选择编程语言,尽量选择熟悉的语言以提高生产效率. ...

  7. 《代码大全2》读书笔记 Week 1

    <代码大全2>第一.二.三章 隐喻思维在西方是一个热门的话题,隐喻的认知功能在各个学科正受到越来越多的重视,依照我的理解,其实就是以众所周知或者理解主体熟悉的事物为符号去将新事物.新概念具 ...

  8. 各种页面刷新代码大全,asp/javascript刷新页面代码

    页面自动刷新代码大全,基本上所有要求自动刷新页面的代码都有,大家可以自由发挥做出完美的页面. 1) 10表示间隔10秒刷新一次 2) <script> window.location.re ...

  9. bat小游戏代码大全_Python打砖块小游戏源代码

    这次用Python实现的是一个接球打砖块的小游戏,最核心的就是:碰撞检测的数学模型 程序运行截图: 其实,编程问题到最后就是数学问题,这个游戏涉及到2D圆形与矩形的碰撞检测问题: 碰撞检测原理:通过找 ...

最新文章

  1. java mybatis enum_mybatis处理枚举类的简单方法
  2. optee HSM的实现
  3. java多态的应用场景_Java开发笔记(五十一)多态的发生场景
  4. python打印进度条starting...done_python打印进度条-tqdm
  5. 无法打开“XXXX”,因为Apple无法检查其是否包含恶意软件。怎么解决?
  6. vv7无法启动显示发动机故障_点火系统故障引起发动机不能启动的排除方法
  7. 德国80%的统计学教授都会答错的6个与P值有关的问题!
  8. 干货:结合Scikit-learn介绍几种常用的特征选择方法
  9. Java线程面试题TOP50
  10. Select显示多级分类列表
  11. spring boot 事务_Redis 事务在 SpringBoot 中的应用
  12. 统计字符串、九宫格、编码问题
  13. 【时间序列】时序分析之移动平均-python实战
  14. ThreeJS 跨域
  15. gin:通过dockerfile部署
  16. 职业学校计算机和机电哪个好,职业学校都有什么专业10大热门专业
  17. python.exe换电脑后无法正常运行_暴雪游戏无法启动,会有卡包吗?
  18. 软件测试面试中关于线上bug,线上出现bug测试人员怎么办
  19. 电脑某个服务器的网站都打不开,电脑某个网站打不开的解决方法
  20. 财务金融工具-生成收付款计划

热门文章

  1. vs2017可用序列号
  2. java map foreach_java foreach遍历map集合的方法案例
  3. CSS面试题汇总(一)
  4. c语言字符串转数字,数字转字符串
  5. 如何将WPS云文档创建到计算机,WPS怎么添加电脑上的文件夹到云文档
  6. Qt 中文翻译 ts文件下载链接
  7. OpenStack面试宝典
  8. Redis全配置文件
  9. 3大常用PCB设计软件AD、PADS、Allegro应该学哪个?
  10. vue+海康威视web3.2无插件版本使用