图的应用:寻路(迷宫游戏), 搜索引擎,网络爬虫
1.图相关的概念
图也是一种非线性结构
图是顶点和边的一个集合
顶点:图中的每个结点都是顶点
边:顶点之间的联系
顶点的度:该顶点有多少条边跟它连接,边的数量就是度数
2.图的存储(代码)
图的存储有两种方法
第一种:邻接矩阵
第二种:邻接表
//定义一个结构体表示边链表
struct edge
{
int n; //跟某个结点相连接的结点下标
struct edge *next; //指向下一个边链表结点
};
//定义一个结构体来表示顶点信息
struct vertex
{
char data; //顶点中的数据
struct edge *listhead; //指向边链表的第一个结点的指针
}
同样一个图,采用邻接矩阵或者邻接表,存储的结果很有可能不同(原因是由于顶点的顺序不同导致)
3.图的遍历(掌握遍历的规则)
有两种遍历方式:
第一种:深度优先遍历(DFS)
规则:类似于二叉树先序遍历
第二种:广度优先遍历(BFS)
规则:类似于二叉树层序遍历
图的邻接矩阵
#include "myhead.h"
//定义一个结构体表示邻接矩阵
struct Graph
{
//定义数组存放顶点信息
char vexter[5];
//定义数组存放边的信息
int edge[5][5];
};
//初始化你的图
struct Graph *graph_init()
{
struct Graph *graph=malloc(sizeof(struct Graph));
//大部分都习惯按照字母顺序依次存放顶点信息
//但是如果顶点中存放的不是字母呢,你又该按照何种顺序存储顶点呢?--》不要究竟,你开心就好
graph->vexter[0]='A';
graph->vexter[1]='B';
graph->vexter[2]='C';
graph->vexter[3]='D';
graph->vexter[4]='E';
//一旦刚才顶点的存储顺序确定好了,那么边中的信息必须严格按照刚才顶点的顺序去初始化
graph->edge[0][0]=0
graph->edge[0][1]=1
graph->edge[0][2]=1
graph->edge[0][3]=1
graph->edge[0][4]=0
graph->edge[1][0]=1
graph->edge[1][1]=0
graph->edge[1][2]=0
graph->edge[1][3]=1
graph->edge[1][4]=0
graph->edge[2][0]=1
graph->edge[2][1]=0
graph->edge[2][2]=0
graph->edge[2][3]=0
graph->edge[2][4]=1
graph->edge[3][0]=1
graph->edge[3][1]=1
graph->edge[3][2]=0
graph->edge[3][3]=0
graph->edge[3][4]=1
graph->edge[4][0]=0
graph->edge[4][1]=0
graph->edge[4][2]=1
graph->edge[4][3]=1
graph->edge[4][4]=0
return graph;
}
图的邻接表
#include "myhead.h"
struct edge
{
int n; //跟某个结点相连接的结点下标
struct edge *next; //指向下一个边链表结点
};
//定义一个结构体来表示顶点信息
struct vertex
{
char data; //顶点中的数据
struct edge *listhead; //指向边链表的第一个结点的指针
};
//封装创建边链表结点的函数
struct edge *creat_node(int m)
{
struct edge *newnode=malloc(sizeof(struct edge));
newnode->n=m;
newnode->next=NULL;
return newnode;
}
int main()
{
//定义结构体数组来表示五个顶点
struct vertex vbuf[5];
vbuf[0].data='A';
Vbuf[0].listhead=NULL; //指向A的边链表的指针
vbuf[1].data='B';
Vbuf[1].listhead=NULL; //指向B的边链表的指针
vbuf[2].data='C';
Vbuf[2].listhead=NULL; //指向C的边链表的指针
vbuf[3].data='D';
Vbuf[3].listhead=NULL; //指向D的边链表的指针
vbuf[4].data='E';
Vbuf[4].listhead=NULL; //指向E的边链表的指针
//搞定A的边链表
struct edge *node1=creat_node(1); //1是B的下标
struct edge *node2=creat_node(2); //2是C的下标
struct edge *node3=creat_node(3); //3是D的下标
Vbuf[0].listhead->next=node1;
node1->next=node2;
node2->next=node3;
}