图的深度优先遍历又称为图的深度优先搜索。
本文章分为用邻接矩阵和邻接链表来进行图的深度优先遍历。可以用于个人学习,本人写博客的目的是便于复习和记录所学的重点和难点,所以不全请大家见谅。
- 邻接矩阵
#include <stdio.h>
#include <malloc.h>
#define VERTEXNUM 5
void createGraph(int (*edge)[VERTEXNUM], int start, int end);
void displayGraph(int (*edge)[VERTEXNUM]);
void DFT(int (*edge)[VERTEXNUM],int* vertexStatusArr);
void DFTcore(int (*edge)[VERTEXNUM],int i,int* vertexStatusArr);
int main(void){
//动态创建存放边的二维数组
int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);
int i,j;
for(i=0;i<VERTEXNUM;i++){
for(j=0;j<VERTEXNUM;j++){
edge[i][j] = 0;
}
}
//存放顶点的遍历状态,0:未遍历,1:已遍历
int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
for(i=0;i<VERTEXNUM;i++){
vertexStatusArr[i] = 0;
}
printf("after init:\n");
displayGraph(edge);
//创建图
createGraph(edge,0,3);
createGraph(edge,0,4);
createGraph(edge,3,1);
createGraph(edge,3,2);
createGraph(edge,4,1);
printf("after create:\n");
displayGraph(edge);
//深度优先遍历
DFT(edge,vertexStatusArr);
free(edge);
return 0;
}
//创建图
void createGraph(int (*edge)[VERTEXNUM], int start, int end){
edge[start][end] = 1;
}
//打印存储的图
void displayGraph(int (*edge)[VERTEXNUM]){
int i,j;
for(i=0;i<VERTEXNUM;i++){
for(j=0;j<VERTEXNUM;j++){
printf("%d ",edge[i][j]);
}
printf("\n");
}
}
//深度优先遍历
void DFT(int (*edge)[VERTEXNUM], int* vertexStatusArr){
printf("start DFT graph:\n");
int i;
for(i=0;i<VERTEXNUM;i++){ //为了遍历有断点的一个图
DFTcore(edge,i,vertexStatusArr);
//printf("* % d \n",i);
}
printf("\n");
}
void DFTcore(int (*edge)[VERTEXNUM],int i,int* vertexStatusArr){
if(vertexStatusArr[i] == 1){
return;
}
printf("%d ",i);
vertexStatusArr[i] = 1;
int j;
for(j=0;j<VERTEXNUM;j++){
if(edge[i][j] == 1){
DFTcore(edge, j, vertexStatusArr);
}
}
}
结果:
- 邻接链表
#include <stdio.h>
#include <malloc.h>
#define VERTEXNUM 5
//存放顶点的邻接表元素
typedef struct edge{
int vertex;
struct edge* next;
}st_edge;
void createGraph(st_edge** edge, int start, int end);
void displayGraph(st_edge** edge);
void delGraph(st_edge** edge);
void DFT(st_edge** edge,int* vertexStatusArr);
void DFTcore(st_edge** edge,int i,int* vertexStatusArr);
int main(void){
//动态创建存放边的指针数组
st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
int i;
for(i=0;i<VERTEXNUM;i++){
edge[i] = NULL;
}
//存放顶点的遍历状态,0:未遍历,1:已遍历
int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
for(i=0;i<VERTEXNUM;i++){
vertexStatusArr[i] = 0;
}
printf("after init:\n");
displayGraph(edge);
//创建图
createGraph(edge,0,3);
createGraph(edge,0,4);
createGraph(edge,3,1);
createGraph(edge,3,2);
createGraph(edge,4,1);
printf("after create:\n");
displayGraph(edge);
//深度优先遍历
DFT(edge,vertexStatusArr);
//释放邻接表占用的内存
delGraph(edge);
edge = NULL;
free(vertexStatusArr);
vertexStatusArr = NULL;
return 0;
}
//创建图
void createGraph(st_edge** edge, int start, int end){
st_edge* newedge = (st_edge*)malloc(sizeof(st_edge));
newedge->vertex = end;
newedge->next = NULL;
edge = edge + start;
while(*edge != NULL){
edge = &((*edge)->next);
}
*edge = newedge;
}
//打印存储的图
void displayGraph(st_edge** edge){
int i;
st_edge* p;
for(i=0;i<VERTEXNUM;i++){
printf("%d:",i);
p = *(edge+i);
while(p != NULL){
printf("%d ",p->vertex);
p = p->next;
}
printf("\n");
}
}
//释放邻接表占用的内存
void delGraph(st_edge** edge){
int i;
st_edge* p;
st_edge* del;
for(i=0;i<VERTEXNUM;i++){
p = *(edge+i);
while(p != NULL){
del = p;
p = p->next;
free(del);
}
edge[i] = NULL;
}
free(edge);
}
//深度优先遍历
void DFT(st_edge** edge,int* vertexStatusArr){
printf("start DFT graph:\n");
int i;
for(i=0;i<VERTEXNUM;i++){ //为了遍历有断点的一个图
DFTcore(edge,i,vertexStatusArr);
//printf("* % d \n",i);
}
printf("\n");
}
void DFTcore(st_edge** edge,int i,int* vertexStatusArr){
if(vertexStatusArr[i] == 1){
return;
}
printf("%d ",i);
vertexStatusArr[i] = 1;
st_edge* p = *(edge+i);
while(p != NULL){
DFTcore(edge, p->vertex, vertexStatusArr);
p = p->next;
}
}
结果:
注意事项:
- 一定在充分理解递归的前提下进行学习深度优先遍历||深度优先搜索
- 首先自己先学习深度优先遍历的思路,然后尝试自己去写代码,如果真的不会写,然后参考别人的代码。然后在反复练习,不断复习。一定会把深度优先遍历(邻接表、邻接矩阵)学的彻彻底底、透透测测。
- 一定要有一个敲代码的好习惯,一定要先思考,然后在自己敲代码,最后在参考别的代码进行修改,最后总结。
- 以后写博客要带上输入输出,并且附上结果图。
- 本代码规定最大的节点号为:5,且默认从0-5的。如果只是添加2,3,4,5,在深度优先遍历的时候也会对0,1进行深度遍历。重要的是理解对图的邻接表和邻接链表的遍历思路。