大一萌新,大佬轻喷^ _ ^ 有什么建议可以提出来一起学习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<<'#'<<" ";
else
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)
{
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<<'#'<<" ";
else
cout<<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();
}
运行结果