一、图的数据结构
图有两种存储方式,一种是用矩阵存,一种是用邻接表存。
矩阵存的数据结构:
typedef struct Graph{
int edges[maxsize][maxsize];
int n,e;
//顶点数和边数
}Graph;
邻接表存的数据结构:
//邻接表存储
typedef struct node{
node *next;
}node; //邻接表右边的节点们
typedef struct vnode{
node* firstnode;
int data;
}vnode;//左边第一列节点
typedef struct AGraph{
vnode adjlist[maxsize];
int n,e;//和矩阵存储一样,n是点数,e是边数
}AGraph;
二、图的创建
基于矩阵存储的图的创建:
//建图
Graph create(int a[maxsize][maxsize],int m){
//m是节点数目
Graph g;
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
g.edges[i][j]=a[i][j];
if(a[i][j]!=0){
g.e++;
}
}
}
g.e=g.e/2;
g.n=m;
return g;
}
基于邻接表存储的图的创建(用一个邻接矩阵创建一个邻接表):
AGraph createlj(int a[maxsize][maxsize],int m){
AGraph ag;
ag.n=m;
ag.e=0;
node *nd;
for(int i=0;i<m;i++){
nd=(node *)malloc(sizeof(node));
nd->next=NULL;
ag.adjlist[i].firstnode=nd;
for(int j=0;j<m;j++){
cout<<i<<" "<<j<<endl;
if(a[i][j]!=0){
nd=(node *)malloc(sizeof(node));
nd->adjvex=j;
nd->next=NULL;
nd->next=ag.adjlist[i].firstnode->next;
ag.adjlist[i].firstnode->next=nd;
ag.e++;
}
}
}
return ag;
}
邻接表创建,并输出每一个节点相邻节点的完整函数如下:
#include <iostream>
#include <algorithm>
#include<string.h>
using namespace std;
#define maxsize 20
typedef struct Graph{
int edges[maxsize][maxsize];
int n,e;
//顶点数和边数
}Graph;//矩阵存储
//邻接表存储
typedef struct node{
int adjvex;//存储节点序号
node *next;
}node; //邻接表右边的节点
typedef struct vnode{
node* firstnode;
int data; //存储节点信息
}vnode;//左边第一列节点
typedef struct AGraph{
vnode adjlist[maxsize];
int n,e;
//和矩阵存储一样,n是点数,e是边数
}AGraph;
AGraph createlj(int a[maxsize][maxsize],int m){
AGraph ag;
ag.n=m;
ag.e=0;
node *nd;
for(int i=0;i<m;i++){
nd=(node *)malloc(sizeof(node));
nd->next=NULL;
ag.adjlist[i].firstnode=nd;
for(int j=0;j<m;j++){
if(a[i][j]!=0){
nd=(node *)malloc(sizeof(node));
nd->adjvex=j;
nd->next=NULL;
nd->next=ag.adjlist[i].firstnode->next;
ag.adjlist[i].firstnode->next=nd;
ag.e++;
}
}
}
return ag;
}
int main() {
int m=6;
int a[][maxsize]={{0,1,0,0,1,0},{0,0,0,0,0,0},{0,0,0,1,0,1},{1,1,0,0,1,0},{0,0,0,1,0,1},{0,0,0,0,0,0}};
AGraph mygraph=createlj(a,6);
node *p;
for(int i=0;i<m;i++){
cout<<"节点"<<i<<"的相邻节点为:";
p=mygraph.adjlist[i].firstnode->next;
while(p!=NULL){
cout<<p->adjvex<<" ";
p=p->next;
}
cout<<endl;
}
return 0;
}
结果如下:
三、图的广度优先算法(类似树的层次遍历)
建议先学习树的层次遍历
基于矩阵存储的图的广度优先算法:
//广度优先算法(层次遍历)
void fun(Graph g,int m){
int dot[g.n];
int zhan[maxsize];
int rear=0;int front=0;
//用数组模拟循环队列
for(int i=0;i<g.n;i++)dot[i]=0;
zhan[rear]=m;
rear=(rear+1)%maxsize;
dot[m]=1;
//根节点入队
while(rear!=front){
cout<<zhan[front]<<" ";
for(int i=0;i<g.n;i++){
if(g.edges[zhan[front]][i]!=0&&dot[i]==0){
zhan[rear]=i;
rear=(rear+1)%maxsize;
//节点序号进栈
dot[i]=1;
}
}
front=(front+1)%maxsize;
}
}
完整代码和运行结果:
#include <iostream>
#include <algorithm>
#include<string.h>
using namespace std;
#define maxsize 20
typedef struct Graph{
int edges[maxsize][maxsize];
int n,e;
//顶点数和边数
}Graph;//矩阵存储
//建图
Graph create(int a[maxsize][maxsize],int m){
//m是节点数目
Graph g;
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
g.edges[i][j]=a[i][j];
if(a[i][j]!=0){
g.e++;
}
}
}
g.e=g.e/2;
g.n=m;
return g;
}
//广度优先算法(层次遍历)
void fun(Graph g,int m){
int dot[g.n];
int zhan[maxsize];
int rear=0;int front=0;
//用数组模拟循环队列
for(int i=0;i<g.n;i++)dot[i]=0;
zhan[rear]=m;
rear=(rear+1)%maxsize;
dot[m]=1;
//根节点入队
while(rear!=front){
cout<<zhan[front]<<" ";
for(int i=0;i<g.n;i++){
if(g.edges[zhan[front]][i]!=0&&dot[i]==0){
zhan[rear]=i;
rear=(rear+1)%maxsize;
//节点序号进栈
dot[i]=1;
}
}
front=(front+1)%maxsize;
}
}
int main() {
int m=6;
int a[][maxsize]={{0,1,0,0,1,0},{0,0,0,0,0,0},{0,0,0,1,0,1},{1,1,0,0,1,0},{0,0,0,1,0,1},{0,0,0,0,0,0}};
Graph myg;
myg=create(a,m);
fun(myg,0);
return 0;
}