数据结构——图的存储及转换
大一萌新,大佬轻喷^ _ ^ 有什么建议可以提出来一起学习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.一个指向表结点的指针。
先康康我们需要定义什么
- 表结点的结构体
- 头结点的结构体
- 创建一个邻接表的类,数据域包括:一个头结点数组,结点数,边数。
再康康我们要做什么
- 将结点的值存入头结点数组
- 让用户输入边的信息,创建一个表结点(区分有向图与无向图的不同)
- 将表结点与对应的头结点连接起来
- 格式化输出
#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();
}
运行结果
数据结构——图的存储及转换相关推荐
- 20.0、C语言数据结构——图的存储结构
20.0.C语言数据结构--图的存储结构 图的存储结构相比较线性表与树来说就复杂很多了: 1. 我们回顾下,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放:树结构是一对多的关系,所以我 ...
- 数据结构——图(存储结构)
数据结构--图 图的定义和基本术语 图的类型定义 图的存储结构 数组(邻接矩阵表示法) 网(即有权图)的邻接矩阵表示法 邻接表 邻接表表示法(链式) 图的邻接表存储表示 采用邻接表表示法创建无向网 邻 ...
- 数据结构--图的存储结构
系列文章目录 第九话 数据结构之图的存储 文章目录 一.了解什么是图 二.图的定义和基本术语 三.存储结构之邻接矩阵 1.邻接矩阵的介绍 2.邻接矩阵的创建 3.主函数中实现 四.存储结构之邻接表 ...
- 数据结构——图的存储结构
邻接矩阵法 通过矩阵来表示所有的 有向图的邻接矩阵法 无向图的邻接矩阵法 无向图的矩阵一定是对称的,可以才用压缩存储方式 网的邻接矩阵法 网就是带权值的图,所以数组里面直接放权值,不存在的边用正无穷表 ...
- 数据结构 --- 图的遍历 DFS、BFS
什么是DFS.BFS? 一条线走到底,深度优先遍历,每一个顶点只遍历.只打印一次的方式:DFS.BFS 数据结构 --- 图的存储 单纯地把邻接顶点的邻接顶点打印出来,顶点重复遍历,打印多次 从 A→ ...
- 数据结构——图:极大小连通子图、图的存储结构、图的遍历
图的基本概念: 极大连通子图就是连通分量. 极大连通子图与连通分量在无向图(undirected graph)这个前提下是等同的概念. 极小连通子图: 减去任何一条边就不再连通. 不管树还是二叉树:n ...
- 数据结构之图的存储结构二及其实现
上一节我们讲述了邻接矩阵法实现图,本节再来讲述一下邻接链表法实现图. 邻接链表 邻接表是图的一种链式存储结构.在邻接表中,对图中的每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点vi边(对有 ...
- 数据结构之图的存储结构一及其实现
图的存储结构 由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在存储区中的物理位置来表示元素之间的关系,即图没有顺序映像的存储结构,但可以借助数组的数据类型表示元素之间的关系. ...
- 数据结构——图的邻接表存储
数据结构--图的邻接表存储 功能实现: (1)图的邻接矩阵的储存 (2)深度优先遍历 (3).广度优先遍历 (4)求结点的度 (5)判断图是否连通 (6)求最小生成树 参考代码 #include &l ...
最新文章
- 367. Valid Perfect Square
- 强化学习:如何处理大规模离散动作空间
- OTSU算法对图像二值化
- linux开发教程,Java基础面试题(2)
- JSP的基本构成详解
- 区块链演进及跨域安全解决方案
- gmail cid图片不显示_python爬虫:爬取男生喜欢的图片
- Python应用实战-Clumper库 | 常用的数据操作函数
- java项目定时任务_java项目定时任务实现
- Java的Socket编程
- jQuery模拟页面加载进度条
- Java期末考试知识点复习
- ClearCase截取
- HYSPLIT模型后向轨迹制作
- Android应用锁实现
- windows虚机环境下,如何快速有效的删除大文件夹?
- Electron主进程和渲染进程之间通信
- 部署k8s(15):持久化存储方案
- DZ先生怪谈国标28181之大型监控组网ntpd校时方案
- 如何用 CSS 中写出超级美丽的阴影效果!