图:
图(Graph)结构是一种非线性的数据结构,图在实际生活中有很多例子,比如交通运输网,地铁网络,社交网络,计算机中的状态执行(自动机)等等都可以抽象成图结构。图结构比树结构复杂的非线性结构。
图的构成:顶点,边。
所有的顶点构成一个顶点集合,所有的边构成边的集合,一个完整的图结构就是由顶点集合和边集合组成。图结构在数学上记为以下形式:
G=(V,E) 或者 G=(V(G),E(G))
其中 V(G)表示图结构所有顶点的集合,顶点可以用不同的数字或者字母来表示。E(G)是图结构中所有边的集合,每条边由所连接的两个顶点来表示。
图结构中顶点集合V(G)不能为空,必须包含一个顶点,而图结构边集合可以为空,表示没有边。
图分为有向图和无向图。
如果一个图结构中,所有的边都没有方向性,那么这种图便称为无向图。
一个图结构中,边是有方向性的,那么这种图就称为有向图。
ps:无向图也可以理解成一个特殊的有向图,就是边互相指向对方节点,A指向B,B又指向A。
混合图(mixed graph)
一个图结构中,边同时有的是有方向性有的是无方向型的图。
在生活中混合图这种情况比较常见,比如城市道路中有些道路是单向通行,有的是双向通行。
无向完全图
如果在一个无向图中, 每两个顶点之间都存在条边,那么这种图结构称为无向完全图。典型的无向完全图。
有向完全图
如果在一个有向图中,每两个顶点之间都存在方向相反的两条边,那么这种图结构称为有向完全图。典型的有向完全图。
有向无环图(DAG图)
如果一个有向图无法从某个顶点出发经过若干条边回到该点,则这个图是一个有向无环图。
有向无环图可以利用在区块链技术中。
无权图和有权图
这里的权可以理解成一个数值,就是说节点与节点之间这个边是否有一个数值与它对应,对于无权图来说这个边不需要具体的值。对于有权图节点与节点之间的关系可能需要某个值来表示,比如这个数值能代表两个顶点间的距离,或者从一个顶点到另一个顶点的时间,所以这时候这个边的值就是代表着两个节点之间的关系,这种图被称为有权图;
简单图 ( Simple Graph)
对于节点与节点之间存在两种边,这两种边相对比较特殊
1.自环边(self-loop):节点自身的边,自己指向自己。
2.平行边(parallel-edges):两个节点之间存在多个边相连接。
图的遍历:
有深度优先搜索(dfs)和广度优先搜索(bfs)
dfs:
void DFS(VNode g[],int v,int visited[]){
int w;
visit(v);
visited[v]=1;
w=FirstAdj(g,v);
while(w!=-1){
if(visited[w]==0)
DFS(g,w,visited);
w=nextAdj(g,v);
}
}
void DFSGraph(VNode g[],int visited[],int n){
int i;
for(i=0;i<n;i++){
visited[i]=0;
}
for(i=0;i<n;i++){
if(visited[i]==0)
DFS(g,i,visited);
}
}
bfs:
void BFS(VNode G[],int v,int visited[]){
int w;
visit(v);
visited[v]=1;
EnQueue(q,v);
while(!emptyA(q)){
Dequeue(&q,&v);
w=FirstAdj(g,v);
while(w!=-1){
if(visited[w]==0){
visit(w);
EnQueue(q,w);
visited[w]=1;
}
w=NextAdj(g,v);
}
}
}
void Travel_BFS(VNode g[],int visited[],int n){
int i;
for(i=0;i<n;i++){
visited[i]=0;
}
for(i=0;i<n;i++){
if(visited[i]==0)
BFS(g,i,visited);
}
}
图的建立:
void createGraph(int n,VNode G[]){
int i,e;
Arcnode *p,*q;
printf("input the information of the vertex\n");
for(i=0;i<n;i++){
getdata(G[i]);
G[i].firstarc=NULL;
}
for(i=0;i<n;i++){
printf("create the edges for the %dth vertex\n",i);
scanf("%d",&e);
while(e!=-1){
p=(Arcnode *)malloc(sizeof(Arcnode));
p->next=NULL;
p->adjvex=e;
if(G[i].firstarc==NULL){
G[i].firstarc=p;
}else{
q->next=p;
}
q=p;
scanf("%d",&e);
}
}
}