大一萌新,大佬轻喷^ _ ^ 有什么建议可以提出来一起学习OAO

文章目录

  • 图的邻接矩阵存储
  • 图的邻接表存储
  • 网络的邻接矩阵存储
  • 网络的邻接矩阵存储
  • 邻接矩阵与邻接表的互相转换
    • 邻接矩阵转换为邻接表
    • 邻接表转换为邻接矩阵

图的邻接矩阵存储

先看无向图和有向图的邻接矩阵


可以看到无向图的邻接矩阵一定是对称的,而有向图不一定,在不考虑环的情况下主对角线全为0

先康康我们需要定义什么
1.一个存储结点的数组
2.一个MAX * MAX的矩阵
3.还要知道结点数和边数以便进行操作

再康康我们需要做什么
1.在结点数组中存入结点
2.让用户输入边的信息,根据信息对矩阵特定元素进行变 1
3.还要区分有向图与无向图(无向图的邻接矩阵一定是对称的)
4.格式化输出

#include <iostream>using namespace std;typedef char datatype;const int Max_number=10;class Mgraph
{public:datatype node[Max_number];int Martix[Max_number][Max_number];int num_of_node,num_of_edge;
public:Mgraph();int CreatMgraph();void Travell();
};
Mgraph::Mgraph()
{num_of_node=0;num_of_edge=0;
}
int Mgraph::CreatMgraph()
{char judge;cout<<"有向图(Y),无向图(N),请输入Y/N"<<endl;cin>>judge;for(int i=0;i<num_of_node;i++){for(int j=0;j<num_of_node;j++)Martix[i][j]=0;}for(int i=0;i<num_of_node;i++){cout<<"输入第 "<<i+1<<" 结点的值"<<endl;cin>>node[i];}int row,clo;cout<<"输入每条边对应的两个顶点序号"<<endl;for(int i=0;i<num_of_edge;i++){cout<<"V<i,j> : ";cin>>row>>clo;if(row<=0||clo<=0||row>num_of_node||clo>num_of_node){cout<<"value is illegal!"<<endl;return -1;}Martix[row-1][clo-1]=1;if(judge=='N'||judge=='n')Martix[clo-1][row-1]=1;}return 1;
}void Mgraph::Travell()
{cout<<"  ";for(int i=0;i<num_of_node;i++)cout<<node[i]<<" ";cout<<endl;for(int i=0;i<num_of_node;i++){cout<<node[i]<<" ";for(int j=0;j<num_of_node;j++){cout<<Martix[i][j]<<" ";}cout<<endl;}
}int main()
{Mgraph mygraph;cout<<"请输入图的结点个数"<<endl;cin>>mygraph.num_of_node;if(mygraph.num_of_node>Max_number){cout<<"你的输入超出大小限制"<<endl;return -1;}cout<<"请输入图的边个数"<<endl;cin>>mygraph.num_of_edge;if(mygraph.num_of_edge>mygraph.num_of_node*mygraph.num_of_node){cout<<"你的输入超出大小限制"<<endl;return -1;}int j=mygraph.CreatMgraph();if(j!=-1)mygraph.Travell();
}

运行结果

图的邻接表存储

分别看上方无向图与有向图的邻接表
邻接表是一种链式存储方式,对每个头结点建立一个单链表,表中结点为表结点。
表结点要包括:1.代表的结点的值。 2.指向下一个表结点的指针。 3.边的权值。
头结点要包括:1.头结点的值。2.一个指向表结点的指针。


先康康我们需要定义什么

  1. 表结点的结构体
  2. 头结点的结构体
  3. 创建一个邻接表的类,数据域包括:一个头结点数组,结点数,边数。

再康康我们要做什么

  1. 将结点的值存入头结点数组
  2. 让用户输入边的信息,创建一个表结点(区分有向图与无向图的不同)
  3. 将表结点与对应的头结点连接起来
  4. 格式化输出
#include <iostream>using namespace std;const int Max_of_nodes=10;typedef char datatype;typedef int weighttype;class Listnode
{public:int node;Listnode* next;weighttype weight;
public:Listnode(){node=0;next=NULL;weight=1;}
};class Headnode
{public:datatype data;Listnode* firnode;
public:Headnode(){firnode=NULL;}
};class Map
{public:Headnode mylist[Max_of_nodes];int num_of_node;int num_of_edge;
public:Map();int CreatMap();void ShowMap();
};Map::Map()
{num_of_node=0;num_of_edge=0;
}
int Map::CreatMap()
{char judge;cout<<"有向图(Y),无向图(N),请输入Y/N"<<endl;cin>>judge;for(int i=0;i<num_of_node;i++){cout<<"请输入第 "<<i+1<<" 个结点的值"<<endl;cin>>mylist[i].data;}cout<<"请输入边的信息,例 :1,2代表由第一个结点到第二个结点的边"<<endl;int beginn=1;int over=1;for(int i=0;i<num_of_edge;i++){cout<<"V<i,j> : ";cin>>beginn>>over;if(beginn<1||over<1||beginn>num_of_node||over>num_of_node){cout<<"输入的边信息不合法"<<endl;return -1;}Listnode* p;p=new Listnode;p->node=over;p->next=mylist[beginn-1].firnode;mylist[beginn-1].firnode=p;if(beginn!=over&&(judge=='N'||judge=='n')){Listnode* q;q=new Listnode;q->node=beginn;q->next=mylist[over-1].firnode;mylist[over-1].firnode=q;}}return 1;
}void Map::ShowMap()
{for(int i=0;i<num_of_node;i++){cout<<mylist[i].data;while(mylist[i].firnode!=NULL){cout<<" "<<mylist[i].firnode->node;mylist[i].firnode=mylist[i].firnode->next;}cout<<endl;}
}
int main()
{Map mymap;cout<<"请输入图中结点个数与边个数"<<endl;cin>>mymap.num_of_node>>mymap.num_of_edge;if(mymap.num_of_node>Max_of_nodes||mymap.num_of_node<1){cout<<"输入信息超出范围"<<endl;return -1;}if(mymap.num_of_edge>Max_of_nodes*Max_of_nodes||mymap.num_of_edge<1){cout<<"输入信息超出范围"<<endl;return -1;}{cout<<"输入信息超过设定最大值"<<endl;return -1;}if(mymap.CreatMap()!=-1)mymap.ShowMap();
}

运行结果

网络的邻接矩阵存储

网络就是带权重的图,因此,我们只需要将原来矩阵中的值变成权重就好。
不连通的两点距离用 # 表示

#include <iostream>
#include <stdio.h>
using namespace std;typedef char datatype;const int Max_number=10;class Mgraph
{public:datatype node[Max_number];int Martix[Max_number][Max_number];int num_of_node,num_of_edge;
public:Mgraph();int CreatMgraph();void Travell();
};
Mgraph::Mgraph()
{num_of_node=0;num_of_edge=0;
}
int Mgraph::CreatMgraph()
{for(int i=0;i<num_of_node;i++){for(int j=0;j<num_of_node;j++)Martix[i][j]=-1;}for(int i=0;i<num_of_node;i++){cout<<"输入第 "<<i+1<<" 结点的值"<<endl;cin>>node[i];}char head,tail;int row,clo,weight;cout<<"输入每条边对应的两个顶点,权重"<<endl;for(int i=0;i<num_of_edge;i++){cout<<"V<i,j> weight: ";cin>>head>>tail>>weight;for(int i=0;i<num_of_node;i++){if(node[i]==head){row=i;break;}else if(i==num_of_node-1){cout<<"输入的值不合法"<<endl;return -1;}}for(int i=0;i<num_of_node;i++){if(node[i]==tail)clo=i;}Martix[row][clo]=weight;}return 1;
}void Mgraph::Travell()
{cout<<"  ";for(int i=0;i<num_of_node;i++)cout<<node[i]<<" ";cout<<endl;for(int i=0;i<num_of_node;i++){cout<<node[i]<<" ";for(int j=0;j<num_of_node;j++){if(Martix[i][j]==-1)cout<<'#'<<" ";elsecout<<Martix[i][j]<<" ";}cout<<endl;}
}int main()
{Mgraph mygraph;cout<<"请输入图的结点个数"<<endl;cin>>mygraph.num_of_node;if(mygraph.num_of_node>Max_number){cout<<"你的输入超出大小限制"<<endl;return -1;}cout<<"请输入图的边个数"<<endl;cin>>mygraph.num_of_edge;if(mygraph.num_of_edge>mygraph.num_of_node*mygraph.num_of_node){cout<<"你的输入超出大小限制"<<endl;return -1;}int j=mygraph.CreatMgraph();if(j!=-1){cout<<endl;cout<<"邻接矩阵如下,#代表无穷"<<endl;mygraph.Travell();}cout<<"按任意键结束程序"<<endl;getchar();getchar();
}

运行结果:

网络的邻接矩阵存储

我们需要在上面的邻接矩阵中边结点的数据结构中加上 weight 这个变量,以便我们存储权重

#include <iostream>
#include <stdio.h>
using namespace std;const int Max_of_nodes=10;typedef char datatype;typedef int weighttype;class Listnode
{public:datatype node;Listnode* next;weighttype weight;
public:Listnode(){node=0;next=NULL;weight=1;}
};class Headnode
{public:datatype data;Listnode* firnode;
public:Headnode(){firnode=NULL;}
};class Map
{public:Headnode mylist[Max_of_nodes];int num_of_node;int num_of_edge;
public:Map();int CreatMap();void ShowMap();
};Map::Map()
{num_of_node=0;num_of_edge=0;
}
int Map::CreatMap()
{for(int i=0;i<num_of_node;i++){cout<<"请输入第 "<<i+1<<" 个结点的值"<<endl;cin>>mylist[i].data;}cout<<"输入每条边对应的两个顶点,权重"<<endl;char head,tail;int beginn;weighttype weight;for(int i=0;i<num_of_edge;i++){cout<<"V<i,j> weight: ";cin>>head>>tail>>weight;for(int i=0;i<num_of_node;i++){if(mylist[i].data==head){beginn=i;break;}else if(i==num_of_node-1){cout<<"输入的值不合法"<<endl;return -1;}}Listnode* p;p=new Listnode;p->node=tail;p->weight=weight;p->next=mylist[beginn].firnode;mylist[beginn].firnode=p;}return 1;
}void Map::ShowMap()
{for(int i=0;i<num_of_node;i++){cout<<mylist[i].data;while(mylist[i].firnode!=NULL){cout<<" "<<mylist[i].firnode->node;mylist[i].firnode=mylist[i].firnode->next;}cout<<endl;}
}
int main()
{Map mymap;cout<<"请输入图中结点个数与边个数"<<endl;cin>>mymap.num_of_node>>mymap.num_of_edge;if(mymap.num_of_node>Max_of_nodes||mymap.num_of_node<1){cout<<"输入信息超出范围"<<endl;return -1;}if(mymap.num_of_edge>Max_of_nodes*Max_of_nodes||mymap.num_of_edge<1){cout<<"输入信息超出范围"<<endl;return -1;}if(mymap.CreatMap()!=-1){cout<<"邻接表如下"<<endl;mymap.ShowMap();}cout<<"按任意键结束程序"<<endl;getchar();getchar();
}

运行结果

邻接矩阵与邻接表的互相转换

邻接矩阵转换为邻接表

因为邻接矩阵中存储的内容包括了权重,但没有明确的给出结点次序
所以我们需要用户先输入结点次序,再通过邻接矩阵对应各个边的权重
才能构造出邻接表

#include <iostream>
#include <stdio.h>
using namespace std;const int Max_of_nodes=10;typedef char datatype;typedef char weighttype;class Listnode
{public:datatype node;Listnode* next;weighttype weight;
public:Listnode(){node=0;next=NULL;weight=1;}
};class Headnode
{public:datatype data;Listnode* firnode;
public:Headnode(){firnode=NULL;}
};class Map
{public:Headnode mylist[Max_of_nodes];int num_of_node;int num_of_edge;
public:Map();int CreatMap(char mymartix[Max_of_nodes][Max_of_nodes]);void ShowMap();
};Map::Map()
{num_of_node=0;num_of_edge=0;
}
int Map::CreatMap(char mymartix[Max_of_nodes][Max_of_nodes])
{int head,tail;char weightt;char judge;for(int i=0;i<num_of_node;i++){for(int j=0;j<num_of_node;j++){if(mymartix[i][j]!='#'){head=i;tail=j;weightt=mymartix[i][j];Listnode* p;p=new Listnode;p->node=mylist[tail].data;p->next=mylist[head].firnode;p->weight=weightt;mylist[head].firnode=p;}}}
}
void Map::ShowMap()
{for(int i=0;i<num_of_node;i++){cout<<mylist[i].data;while(mylist[i].firnode!=NULL){cout<<" "<<mylist[i].firnode->node;mylist[i].firnode=mylist[i].firnode->next;}cout<<endl;}
}int main()
{Map mymap;cout<<"请输入结点个数,边数"<<endl;cin>>mymap.num_of_node>>mymap.num_of_edge;char mymartix[Max_of_nodes][Max_of_nodes];cout<<"请输入各个结点的值"<<endl;for(int i=0;i<mymap.num_of_node;i++){cin>>mymap.mylist[i].data;}cout<<"请按行输入邻接矩阵,(输入#代表无穷)!"<<endl;for(int i=0;i<mymap.num_of_node;i++){for(int j=0;j<mymap.num_of_node;j++)cin>>mymartix[i][j];}mymap.CreatMap(mymartix);cout<<"转换后的邻接表为"<<endl;mymap.ShowMap();cout<<"按任意键结束程序"<<endl;getchar();getchar();
}

运行结果

邻接表转换为邻接矩阵

由于邻接表中权重并没有显示地表现在表中
所以我们需要用户输入,创建一个邻接表就像前面那样
然后我们再对邻接表进行处理,生成我们的邻接矩阵

为了方便操作,我定义了一个矩阵元素的类,包括了一个tag位,和一个int型的权重变量
这样,在输出矩阵时就可以很方便地输出# 代表不连通

#include <iostream>
#include <stdio.h>
using namespace std;const int Max_of_nodes=10;typedef char datatype;typedef int weighttype;class Martix_node
{public:int tag;int value;
public:Martix_node(){tag=0;value=0;}
};class Listnode
{public:datatype node;Listnode* next;weighttype weight;
public:Listnode(){node=0;next=NULL;weight=1;}
};class Headnode
{public:datatype data;Listnode* firnode;
public:Headnode(){firnode=NULL;}
};class Map
{public:Headnode mylist[Max_of_nodes];int num_of_node;int num_of_edge;
public:Map();int CreatMap();int CreatMartix();void ShowMap();
};Map::Map()
{num_of_node=0;num_of_edge=0;
}
int Map::CreatMap()
{for(int i=0;i<num_of_node;i++){cout<<"请输入第 "<<i+1<<" 个结点的值"<<endl;cin>>mylist[i].data;}cout<<"输入每条边对应的两个顶点,权重"<<endl;char head,tail;int beginn;weighttype weight;for(int i=0;i<num_of_edge;i++){cout<<"V<i,j> weight: ";cin>>head>>tail>>weight;for(int i=0;i<num_of_node;i++){if(mylist[i].data==head)beginn=i;}Listnode* p;p=new Listnode;p->node=tail;p->weight=weight;p->next=mylist[beginn].firnode;mylist[beginn].firnode=p;}return 1;
}
void Map::ShowMap()
{for(int i=0;i<num_of_node;i++){Listnode* p=mylist[i].firnode;cout<<mylist[i].data;while(p!=NULL){cout<<" "<<p->node;p=p->next;}cout<<endl;}
}int Map::CreatMartix()
{Martix_node mymartix[num_of_node][num_of_node];for(int i=0;i<num_of_node;i++){while(mylist[i].firnode!=NULL){for(int j=0;j<num_of_node;j++){if(mylist[j].data==mylist[i].firnode->node){mymartix[i][j].value=mylist[i].firnode->weight;mymartix[i][j].tag=1;}}mylist[i].firnode=mylist[i].firnode->next;}}cout<<"  ";for(int i=0;i<num_of_node;i++)cout<<mylist[i].data<<" ";cout<<endl;for(int i=0;i<num_of_node;i++){cout<<mylist[i].data<<" ";for(int j=0;j<num_of_node;j++){if(!mymartix[i][j].tag)cout<<'#'<<" ";elsecout<<mymartix[i][j].value<<" ";}cout<<endl;}
}
int main()
{Map mymap;cout<<"请输入图中结点个数与边个数"<<endl;cin>>mymap.num_of_node>>mymap.num_of_edge;if(mymap.num_of_node>Max_of_nodes||mymap.num_of_node<1){cout<<"输入信息超出范围"<<endl;return -1;}if(mymap.num_of_edge>Max_of_nodes*Max_of_nodes||mymap.num_of_edge<1){cout<<"输入信息超出范围"<<endl;return -1;}mymap.CreatMap();cout<<"邻接表为"<<endl;mymap.ShowMap();cout<<"转换后的邻接矩阵为(#代表无穷大)"<<endl;mymap.CreatMartix();cout<<"按任意键结束程序"<<endl;getchar();getchar();
}

运行结果

数据结构——图的存储及转换相关推荐

  1. 20.0、C语言数据结构——图的存储结构

    20.0.C语言数据结构--图的存储结构 图的存储结构相比较线性表与树来说就复杂很多了: 1. 我们回顾下,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放:树结构是一对多的关系,所以我 ...

  2. 数据结构——图(存储结构)

    数据结构--图 图的定义和基本术语 图的类型定义 图的存储结构 数组(邻接矩阵表示法) 网(即有权图)的邻接矩阵表示法 邻接表 邻接表表示法(链式) 图的邻接表存储表示 采用邻接表表示法创建无向网 邻 ...

  3. 数据结构--图的存储结构

    系列文章目录 第九话  数据结构之图的存储 文章目录 一.了解什么是图 二.图的定义和基本术语 三.存储结构之邻接矩阵 1.邻接矩阵的介绍 2.邻接矩阵的创建 3.主函数中实现 四.存储结构之邻接表 ...

  4. 数据结构——图的存储结构

    邻接矩阵法 通过矩阵来表示所有的 有向图的邻接矩阵法 无向图的邻接矩阵法 无向图的矩阵一定是对称的,可以才用压缩存储方式 网的邻接矩阵法 网就是带权值的图,所以数组里面直接放权值,不存在的边用正无穷表 ...

  5. 数据结构 --- 图的遍历 DFS、BFS

    什么是DFS.BFS? 一条线走到底,深度优先遍历,每一个顶点只遍历.只打印一次的方式:DFS.BFS 数据结构 --- 图的存储 单纯地把邻接顶点的邻接顶点打印出来,顶点重复遍历,打印多次 从 A→ ...

  6. 数据结构——图:极大小连通子图、图的存储结构、图的遍历

    图的基本概念: 极大连通子图就是连通分量. 极大连通子图与连通分量在无向图(undirected graph)这个前提下是等同的概念. 极小连通子图: 减去任何一条边就不再连通. 不管树还是二叉树:n ...

  7. 数据结构之图的存储结构二及其实现

    上一节我们讲述了邻接矩阵法实现图,本节再来讲述一下邻接链表法实现图. 邻接链表 邻接表是图的一种链式存储结构.在邻接表中,对图中的每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点vi边(对有 ...

  8. 数据结构之图的存储结构一及其实现

    图的存储结构 由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在存储区中的物理位置来表示元素之间的关系,即图没有顺序映像的存储结构,但可以借助数组的数据类型表示元素之间的关系. ...

  9. 数据结构——图的邻接表存储

    数据结构--图的邻接表存储 功能实现: (1)图的邻接矩阵的储存 (2)深度优先遍历 (3).广度优先遍历 (4)求结点的度 (5)判断图是否连通 (6)求最小生成树 参考代码 #include &l ...

最新文章

  1. 367. Valid Perfect Square
  2. 强化学习:如何处理大规模离散动作空间
  3. OTSU算法对图像二值化
  4. linux开发教程,Java基础面试题(2)
  5. JSP的基本构成详解
  6. 区块链演进及跨域安全解决方案
  7. gmail cid图片不显示_python爬虫:爬取男生喜欢的图片
  8. Python应用实战-Clumper库 | 常用的数据操作函数
  9. java项目定时任务_java项目定时任务实现
  10. Java的Socket编程
  11. jQuery模拟页面加载进度条
  12. Java期末考试知识点复习
  13. ClearCase截取
  14. HYSPLIT模型后向轨迹制作
  15. Android应用锁实现
  16. windows虚机环境下,如何快速有效的删除大文件夹?
  17. Electron主进程和渲染进程之间通信
  18. 部署k8s(15):持久化存储方案
  19. DZ先生怪谈国标28181之大型监控组网ntpd校时方案
  20. 如何用 CSS 中写出超级美丽的阴影效果!

热门文章

  1. CyberVein贡献奖赏计划 全新启动
  2. Android 12.0 Settings 去掉打开开发者模式和USB调试模式的广播
  3. mybatis+springMVC+spring原理及工作流程
  4. 3D Coat中文版
  5. 什么是二级网站域名?
  6. 网络游戏中的协议选择
  7. SQL SUM() 函数
  8. JAVA SpringBoot从零到商用化校园商铺平台的开发实战(毕设)
  9. python-------函数的定义与使用,调用与分类。
  10. 第六届中国图学大会草记