数据结构 图的遍历(广度优先遍历、深度优先遍历)
8.6、图的广度优先遍历
- 找到与顶点相邻的所有顶点,
- 标记哪些顶点被访问过
- 需要一个辅助队列
#include <stdio.h> #include <stdlib.h> #include<math.h> #define MaxSize 100 #define boolean int #define true 1 #define false 0 //邻接矩阵存储图的信息 typedef struct MGraph{ char Vex[MaxSize];//顶点信息 int Edge[MaxSize][MaxSize];//邻接矩阵 int vexnum,arcnum;//顶点数和边数 }MGraph; //初始化一个邻接矩阵 boolean MG_Init(MGraph **G){ *G = (MGraph*)malloc(sizeof(MGraph)); if((*G) == NULL) return false;//申请空间失败 (*G)->vexnum = 0;//顶点数为0 (*G)->arcnum = 0;//边数为0 // for(int i = 0;i < MaxSize;i++){ // for(int j = 0;j < MaxSize;j++){ // (*G)->Edge[i][j] = 0; // } // } return true; } //获取该结点v的索引 int GetV_Index(MGraph *G,char v){ for(int i = 0;i<G->vexnum;i++){ if(G->Vex[i] == v) return i; } return -1; } //判断图中是否有结点v boolean IsVEmpty(MGraph *G,char v){ for(int i=0;i<G->vexnum;i++){ if(G->Vex[i] == v) return true;//存在 } return false;//不存在 } //判断图中是否存在该边;传入边 boolean Adjancent(MGraph *G,char v,char w){ int vi = GetV_Index(G,v); int wi = GetV_Index(G,w); return G->Edge[vi][wi]; } //判断图中是否存在该边;传入边的索引 boolean Adjancent1(MGraph *G,int vi,int wi){ if(G->Edge[vi][wi] == 1) return true; else return false; } //插入一个新的顶点 boolean InsertV(MGraph *G,char v){ if(G->vexnum >= MaxSize || IsVEmpty(G,v)){ printf("存储顶点数的空间满了或者改结点存在!\n"); return false; } G->Vex[G->vexnum++] = v; return true; } //插入边(v,w) boolean AddEdge(MGraph *G,char v,char w){ if(!IsVEmpty(G,v) || !IsVEmpty(G,w)){ printf("输入的边其中有一个顶点或者两个顶点不存在\n"); return false; } //获取结点的索引 int vi = GetV_Index(G,v); int wi = GetV_Index(G,w); if(Adjancent1(G,vi,wi)){ printf("该边已经存在\n"); return false; } //修改邻接矩阵 G->Edge[vi][wi] = 1; G->Edge[wi][vi] = 1; //修改边数 G->arcnum++; return true; } //删除边(v,w) boolean RemoveEdge(MGraph *G,char v,char w){ if(!IsVEmpty(G,v) || !IsVEmpty(G,w)){ //判断这两个点是否存在 printf("这两个点不存在\n"); return false; } int vi = GetV_Index(G,v); int wi = GetV_Index(G,w); if(Adjancent1(G,vi,wi) == true){//存在该边就删除 G->Edge[vi][wi] = 0; G->Edge[wi][vi] = 0; G->arcnum--;//边减1 return true; }else{ printf("删除的边不存在\n"); return false; } } //获取某个结点v的所有邻接边 boolean NeighBors(MGraph *G,char v,char ***res,int *length){ if(!IsVEmpty(G,v)){ printf("输入的顶点不存在\n"); return false; } int vi = GetV_Index(G,v); for(int i = 0;i < G->vexnum;i++){ if(G->Edge[vi][i] == 1) { (*length)++; } } *res = (char **)malloc(sizeof(char)*(*length)); int index = 0; for(int i = 0;i < G->vexnum;i++){ if(G->Edge[vi][i] == 1) { (*res)[index] = (char *)malloc(sizeof(char)*2); (*res)[index][0] = v; (*res)[index][1] = G->Vex[i]; index++; } } return true; } //队列的数据信息 typedef struct ElemType{ int index; char v; }ElemType; //结点 typedef struct LinkNode{ ElemType data; struct LinkNode *next; }LinkNode; //链队列定义 typedef struct{ LinkNode *front,*rear;//*front 队头指针, *rear 队尾指针 }LinkQueue; //初始化带头结点的队列 int InitLinkQueue(LinkQueue *Q){ (*Q).front = (*Q).rear = (LinkNode *)malloc(sizeof(LinkNode)); if((*Q).front == NULL || (*Q).rear == NULL) return false; (*Q).front->next = NULL; return true; }; //带头结点判断是否为空 int IsEmpty(LinkQueue Q){ if(Q.front == Q.rear) return true; else return false; } //带头结点入队操作 int EnQueue(LinkQueue *Q,ElemType e){ LinkNode *p = (LinkNode *)malloc(sizeof(LinkNode)); if(p==NULL) return false;//分配内存失败 p->data = e; p->next = NULL; Q->rear->next = p; Q->rear = p; } //带头结点出队操作 int DeQueue(LinkQueue *Q,ElemType *e){ if(Q->front == Q->rear) return false;//队列为空,出队失败 LinkNode *p = Q->front->next; *e = p->data; Q->front->next = p->next; if(Q->rear == p){ //如果出队的元素是对尾元素,需要特殊处理 Q->rear = Q->front; } free(p);//释放片 return true; } //寻找某个结点V的所有邻接点 boolean Neighbors(MGraph *G,char V,int Vi,char **resNode,int **resIndex,int *length){ for(int i = 0;i < G->vexnum;i++){ if(G->Edge[Vi][i] == 1){ (*length)++; } } *resNode = (char *)malloc(sizeof(char)*(*length)); *resIndex = (int *)malloc(sizeof(int)*(*length)); int index = 0; for(int i = 0;i < G->vexnum;i++){ if(G->Edge[Vi][i] == 1){ (*resNode)[index] = G->Vex[i]; (*resIndex)[index] = i; index++; } } return true; } //广度优先遍历 void BFS(MGraph *G,char V,int Vi,char **res,int *resLength,boolean **visited){ LinkQueue Q; InitLinkQueue(&Q); ElemType e; e.index = Vi; e.v = V; (*visited)[Vi] = true; EnQueue(&Q,e); while(!IsEmpty(Q)){ DeQueue(&Q,&e); (*res)[*resLength] = e.v; (*resLength)++; char *resChar; int *resIndex; int length = 0; Neighbors(G,e.v,e.index,&resChar,&resIndex,&length); for(int i = 0;i < length;i++){ if((*visited)[resIndex[i]] == false){ (*visited)[resIndex[i]] = true; ElemType e1; e1.index = resIndex[i]; e1.v = resChar[i]; EnQueue(&Q,e1); } } } } //访问结点 void visitV(char *res,int resLength){ for(int i = 0;i < resLength;i++){ printf("%c ,",res[i]); } } //对图G进行广度优先遍历 void BFSMGraph(MGraph *G,char V){ int Vi = GetV_Index(G,V); char *res = (char *)malloc(sizeof(char)*G->vexnum); int resLength = 0; boolean *visited = (boolean *)malloc(sizeof(boolean)*G->vexnum); for(int i = 0;i < G->vexnum;i++){ visited[i] = false; } BFS(G,'A',Vi,&res,&resLength,&visited); for(int i = 0;i < G->vexnum;i++){ if(visited[i] == false){ BFS(G,G->Vex[i],i,&res,&resLength,&visited); } } visitV(res,resLength); } int main(){ MGraph *G; MG_Init(&G); printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum); InsertV(G,'A'); InsertV(G,'B'); InsertV(G,'C'); InsertV(G,'D'); InsertV(G,'E'); InsertV(G,'F'); InsertV(G,'G'); InsertV(G,'H'); InsertV(G,'I'); InsertV(G,'J'); InsertV(G,'K'); printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum); AddEdge(G,'A','B'); AddEdge(G,'A','C'); AddEdge(G,'C','D'); AddEdge(G,'D','E'); AddEdge(G,'D','F'); AddEdge(G,'E','F'); AddEdge(G,'E','G'); AddEdge(G,'F','G'); AddEdge(G,'F','H'); AddEdge(G,'G','H'); AddEdge(G,'I','J'); AddEdge(G,'J','K'); AddEdge(G,'I','K'); printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum); BFSMGraph(G,'A'); return 0; } //结果: 顶点数:0;边数:0 顶点数:11;边数:0 顶点数:11;边数:13 A ,B ,C ,D ,E ,F ,G ,H ,I ,J ,K ,
广度生成树
8.7、图的深度优先遍历
沿着一条路径往里面找,直到找不到结点才返回
使用递归的思想来完成
#include <stdio.h> #include <stdlib.h> #include<math.h> #define MaxSize 100 #define boolean int #define true 1 #define false 0 //邻接矩阵存储图的信息 typedef struct MGraph{ char Vex[MaxSize];//顶点信息 int Edge[MaxSize][MaxSize];//邻接矩阵 int vexnum,arcnum;//顶点数和边数 }MGraph; //初始化一个邻接矩阵 boolean MG_Init(MGraph **G){ *G = (MGraph*)malloc(sizeof(MGraph)); if((*G) == NULL) return false;//申请空间失败 (*G)->vexnum = 0;//顶点数为0 (*G)->arcnum = 0;//边数为0 // for(int i = 0;i < MaxSize;i++){ // for(int j = 0;j < MaxSize;j++){ // (*G)->Edge[i][j] = 0; // } // } return true; } //获取该结点v的索引 int GetV_Index(MGraph *G,char v){ for(int i = 0;i<G->vexnum;i++){ if(G->Vex[i] == v) return i; } return -1; } //判断图中是否有结点v boolean IsVEmpty(MGraph *G,char v){ for(int i=0;i<G->vexnum;i++){ if(G->Vex[i] == v) return true;//存在 } return false;//不存在 } //判断图中是否存在该边;传入边 boolean Adjancent(MGraph *G,char v,char w){ int vi = GetV_Index(G,v); int wi = GetV_Index(G,w); return G->Edge[vi][wi]; } //判断图中是否存在该边;传入边的索引 boolean Adjancent1(MGraph *G,int vi,int wi){ if(G->Edge[vi][wi] == 1) return true; else return false; } //插入一个新的顶点 boolean InsertV(MGraph *G,char v){ if(G->vexnum >= MaxSize || IsVEmpty(G,v)){ printf("存储顶点数的空间满了或者改结点存在!\n"); return false; } G->Vex[G->vexnum++] = v; return true; } //插入边(v,w) boolean AddEdge(MGraph *G,char v,char w){ if(!IsVEmpty(G,v) || !IsVEmpty(G,w)){ printf("输入的边其中有一个顶点或者两个顶点不存在\n"); return false; } //获取结点的索引 int vi = GetV_Index(G,v); int wi = GetV_Index(G,w); if(Adjancent1(G,vi,wi)){ printf("该边已经存在\n"); return false; } //修改邻接矩阵 G->Edge[vi][wi] = 1; G->Edge[wi][vi] = 1; //修改边数 G->arcnum++; return true; } //删除边(v,w) boolean RemoveEdge(MGraph *G,char v,char w){ if(!IsVEmpty(G,v) || !IsVEmpty(G,w)){ //判断这两个点是否存在 printf("这两个点不存在\n"); return false; } int vi = GetV_Index(G,v); int wi = GetV_Index(G,w); if(Adjancent1(G,vi,wi) == true){//存在该边就删除 G->Edge[vi][wi] = 0; G->Edge[wi][vi] = 0; G->arcnum--;//边减1 return true; }else{ printf("删除的边不存在\n"); return false; } } //获取某个结点v的所有邻接边 boolean NeighBors(MGraph *G,char v,char ***res,int *length){ if(!IsVEmpty(G,v)){ printf("输入的顶点不存在\n"); return false; } int vi = GetV_Index(G,v); for(int i = 0;i < G->vexnum;i++){ if(G->Edge[vi][i] == 1) { (*length)++; } } *res = (char **)malloc(sizeof(char)*(*length)); int index = 0; for(int i = 0;i < G->vexnum;i++){ if(G->Edge[vi][i] == 1) { (*res)[index] = (char *)malloc(sizeof(char)*2); (*res)[index][0] = v; (*res)[index][1] = G->Vex[i]; index++; } } return true; } //寻找某个结点V的所有邻接点 boolean Neighbors(MGraph *G,char V,int Vi,char **resNode,int **resIndex,int *length){ for(int i = 0;i < G->vexnum;i++){ if(G->Edge[Vi][i] == 1){ (*length)++; } } *resNode = (char *)malloc(sizeof(char)*(*length)); *resIndex = (int *)malloc(sizeof(int)*(*length)); int index = 0; for(int i = 0;i < G->vexnum;i++){ if(G->Edge[Vi][i] == 1){ (*resNode)[index] = G->Vex[i]; (*resIndex)[index] = i; index++; } } return true; } //访问结点 void visitV(char *res,int resLength){ for(int i = 0;i < resLength;i++){ printf("%c ,",res[i]); } } //深度优先遍历 void DFS(MGraph *G,char V,int Vi,char **res,int *resLength,boolean **visited){ (*visited)[Vi] = true; (*res)[*resLength] = V; (*resLength)++; char *resChar; int *resIndex; int length = 0; Neighbors(G,V,Vi,&resChar,&resIndex,&length); for(int i = 0;i < length;i++){ if((*visited)[resIndex[i]] == false){ DFS(G,resChar[i],resIndex[i],res,resLength,visited); } } } //对图G进行广度优先遍历 void DFSMGraph(MGraph *G,char V){ int Vi = GetV_Index(G,V); char *res = (char *)malloc(sizeof(char)*G->vexnum); int resLength = 0; boolean *visited = (boolean *)malloc(sizeof(boolean)*G->vexnum); for(int i = 0;i < G->vexnum;i++){ visited[i] = false; } DFS(G,V,Vi,&res,&resLength,&visited); for(int i = 0;i < G->vexnum;i++){ if(visited[i] == false){ DFS(G,G->Vex[i],i,&res,&resLength,&visited); } } visitV(res,resLength); } int main(){ MGraph *G; MG_Init(&G); printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum); InsertV(G,'A'); InsertV(G,'B'); InsertV(G,'C'); InsertV(G,'D'); InsertV(G,'E'); InsertV(G,'F'); InsertV(G,'G'); InsertV(G,'H'); InsertV(G,'I'); InsertV(G,'J'); InsertV(G,'K'); printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum); AddEdge(G,'A','B'); AddEdge(G,'A','C'); AddEdge(G,'C','D'); AddEdge(G,'D','E'); AddEdge(G,'D','F'); AddEdge(G,'E','F'); AddEdge(G,'E','G'); AddEdge(G,'F','G'); AddEdge(G,'F','H'); AddEdge(G,'G','H'); AddEdge(G,'I','J'); AddEdge(G,'J','K'); AddEdge(G,'I','K'); printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum); DFSMGraph(G,'C'); return 0; } //结果: 顶点数:0;边数:0 顶点数:11;边数:0 顶点数:11;边数:13 C ,A ,B ,D ,E ,F ,G ,H ,I ,J ,K ,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)