1:基本概念:
图:图G是由两个集合V (G)和E(G)所组成,记为G=(V,E);其中V (G)是图顶点的非空有限集合,E(G)是图中边的有限集合。
有向图:V(G1)={v1,v2,v3};
E(G1)={<V1,V2>,<V2,V1>,<V2,V2>}
无向图:V(G2)={v1,v2,v3,v4};
E(G2)={(V1,V2),(V1,V3),(V1,V4),(v2,v3),(v2,v4),(v3,v4)}
2:图的存储结构:
对于如下的有向图:
(1)邻接矩阵:使用一个二维数组的方法,对于存在的边(u,v),我们置A[u][v]=1,否则为0;优点是非常简单,但是空间需求则为@(|V|^2),(|V|为顶点的个数),如果图是稠密的话,那么这种表示还算合理,但往往情况并非如此。
(2)邻接表:建立一张表,表的表头分别为每个顶点,那么空间需求为O(|E|+|V|)。(边的个数+顶点个数)。对于稀疏表,这个应用相当广泛。下图是其表示方法:
顺便提下,在实际应用中,顶点都是有名字的而非单纯的数字。那么我们应该联想到散列表,所以要结合散列表应用。
(3) 遍历:深度优先遍历。
针对以下无向图,写出深度优先遍历
首先,我们从A点开始。此时,标记A为访问过的并递归调用Dfs(B)。Dfs(B)标记B为访问过的并递归调用Dfs(C)。Dfs(C)标记C为访问过的并递归调用Dfs(D)。 Dfs(D)标记D为访问过的并发现ABC均是访问过的节点,那么返回到Dfs(C),Dfs(C)看到B没有标记,那么递归调用Dfs(E)。那么递归调用Dfs(E)。
递归调用Dfs(E)标记E为访问过的顶点,也发现ABC均为访问过的顶点,那么返回Dfs(C),再依次返回Dfs(B),Dfs(A)。
因为采用邻接表的方法,用Visited[]来标记是否被访问过,我们知道只要消耗O(V)的时间就能遍历所有的节点,每个顶点操作的总的时间消耗需要O(e)的时间,所以说此算法总共需要O(e+V)的时间。
C代码如下所示:
#include <stdio.h>
#include <stdlib.h>
#define Max_VerTex 6//最大的顶点数
//为什么会有node和vnode呢,它们貌似是可以合并的,但是对于后面的
//代码的编写,会发现分开后代码容易写
typedef struct node{
int value;//每个顶点的位置(即1,2,3,4,5,6...)
struct node *next;//每个节点指向下一个节点
}node;
typedef struct vnode{
int info;//一张邻接表的 表头的信息 在这个 程序中没有必要存在
node *firstnode;//表示表头连接的第一个节点
}vnode;
typedef struct graph{
vnode table[Max_VerTex];//生成一张邻接表
int vertex_num;
int edge_num; //边和顶点数
}graph;
static int visited[Max_VerTex];
static graph *gp;
//建立连接表
void initial(){
int i= 0;
int index;
int point_value;
node *newnode;
node *temp_node;
int g_array[12][2]={{1,2},{1,3},{2,1},{2,4},{2,5},
{4,2},{4,6},{6,4},{6,5},{5,2},{5,6},
{3,1}};
//基本的初始化操作
gp = (graph *)malloc(sizeof(graph));
gp->vertex_num = 6;
gp->edge_num = 12;
for(;i<gp->vertex_num;i++){
gp->table[i].firstnode = (node *)malloc(sizeof(node));
gp->table[i].firstnode->value = i+1;
gp->table[i].firstnode->next = NULL;
}
//建立邻接表的关键部分
for(i=0;i<gp->edge_num;i++){
index = g_array[i][0]-1;
point_value = g_array[i][1];
newnode = (node *)malloc(sizeof(node));
newnode->value = point_value;
newnode->next=NULL;
temp_node = gp->table[index].firstnode;
while(temp_node->next != NULL){
temp_node = temp_node->next;
}
temp_node->next=newnode;
}
return;
}
void DFSTraverse(int i){
node *temp_node;
visited[i]=1;
printf("%d ",i+1);
temp_node=gp->table[i].firstnode->next;
while(temp_node != NULL){
if(visited[temp_node->value-1]==0){
DFSTraverse(temp_node->value-1);
}
temp_node=temp_node->next;
}
return;
}
void Dfs(){
int i;
for(i=0;i<gp->vertex_num;i++){
visited[i]=0;
}
i=0;
// for(i=0;i<gp->vertex_num;i++){//此条语句是用于非单连通的图使用的
if(visited[i]==0){
DFSTraverse(i);
}
// }
}
void main(){
initial();
Dfs();
}