为了账号安全,请及时绑定邮箱和手机立即绑定

c/c++连通图的遍历(深度遍历/广度遍历)

标签:
C C++

https://img1.sycdn.imooc.com//5c4dc5a200013f7802910169.jpg

连通图的遍历(深度遍历/广度遍历)

概念:图中的所有节点都要遍历到,并且只能遍历一次。

  • 深度遍历

  • 广度遍历

深度遍历

概念:从一个给定的顶点开始,找到一条边,沿着这条边一直遍历。

广度遍历

概念:从一个给定的顶点开始,找到这个顶点下的所有子顶点后,再找下一层的子顶点。

深度遍历的实现思路

1,创建一个bool数组,用来识别哪个顶点已经被遍历过了。

2,递归

3,递归找给定顶点是否有下一个顶点(方法:get_first_neighbor),都找完后,

4,再递归找给定顶点之后的在3处找到的顶点后的下一个顶点(方法:get_next_neighbor)

光度遍历的实现思路

1,用队列实现,先入队给定顶点

2,出队

3,入队:与在2处出队的顶点有相连的顶点

代码

graph_link.h

#ifndef __graph_link__#define __graph_link__#include <stdio.h>#include <malloc.h>#include <assert.h>#include <memory.h>#include <stdbool.h>#define default_vertex_size 10#define T char//边的结构typedef struct Edge{
  //顶点的下标
  int idx;  //指向下一个边的指针
  struct Edge* link;}Edge;//顶点的结构typedef struct Vertex{
  //顶点的值
  T data;  //边
  Edge* adj;
}Vertex;//图的结构typedef struct GraphLink{
  int MaxVertices;  int NumVertices;  int NumEdges;

  Vertex* nodeTable;
}GraphLink;//初始化图void init_graph_link(GraphLink* g);//显示图void show_graph_link(GraphLink* g);//插入顶点void insert_vertex(GraphLink* g, T v);//插入边尾插void insert_edge_tail(GraphLink* g, T v1, T v2);//插入边头插void insert_edge_head(GraphLink* g, T v1, T v2);//删除边void remove_edge(GraphLink* g, T v1, T v2);//删除顶点void remove_vertex(GraphLink* g, T v);//销毁图void destroy_graph_link(GraphLink* g);//取得指定顶点的第一个后序顶点int get_first_neighbor(GraphLink* g, T v);//取得指定顶点v1的临街顶点v2的第一个后序顶点int get_next_neighbor(GraphLink* g, T v1, T v2);//深度遍历void dfs_graph(GraphLink* g, T v);//取得顶点的data值T getVertexValue(GraphLink* g, int i);//广度遍历void cfs_graph(GraphLink* g, T v);#endif

graph_link.c

#include "graph_link.h"#include "nodequeue.h"//初始化图void init_graph_link(GraphLink* g){
  g->MaxVertices = default_vertex_size;
  g->NumVertices = g->NumEdges = 0;

  g->nodeTable = (Vertex*)malloc(sizeof(Vertex) * g->MaxVertices);
  assert(NULL != g->nodeTable);  for(int i = 0; i < g->MaxVertices; ++i){
    g->nodeTable[i].adj = NULL;
  }
}//显示图void show_graph_link(GraphLink* g){  
if(NULL == g)return;  
for(int i = 0; i < g->NumVertices; ++i){    
printf("%d %c->", i, g->nodeTable[i].data);
    Edge* p = g->nodeTable[i].adj;    
    while(NULL != p){      
    printf("%d->", p->idx);
      p = p->link;
    }    printf(" NULL\n");
  }
}//插入顶点void insert_vertex(GraphLink* g, T v){  
if(g->NumVertices >= g->MaxVertices)return;
  g->nodeTable[g->NumVertices++].data = v;
}//查找顶点的indexint getVertexIndex(GraphLink* g, T v){  
for(int i = 0; i < g->NumVertices; ++i){   
 if(v == g->nodeTable[i].data)return i;
  }  return -1;
}//插入边(头插)void insert_edge_head(GraphLink* g, T v1, T v2){  
int p1 = getVertexIndex(g, v1);  int p2 = getVertexIndex(g, v2);  
if(p1 == -1 || p2 == -1)return;

  Edge* p = (Edge*)malloc(sizeof(Edge));
  p->idx = p2;
  p->link = g->nodeTable[p1].adj;
  g->nodeTable[p1].adj = p;
  
  p = (Edge*)malloc(sizeof(Edge));
  p->idx = p1;
  p->link = g->nodeTable[p2].adj;
  g->nodeTable[p2].adj = p;  
}//取得指定顶点的第一个后序顶点int get_first_neighbor(GraphLink* g, T v){  
int i = getVertexIndex(g, v);  
if (-1 == i)return -1;
  Edge* p = g->nodeTable[i].adj;  
  if(NULL != p)    
  return p->idx;  
  else
    return -1;
}//取得指定顶点v1的临街顶点v2的第一个后序顶点int get_next_neighbor(GraphLink* g, T ve1, T ve2){  int v1 = getVertexIndex(g, ve1);  int v2 = getVertexIndex(g, ve2);  if(v1 == -1 || v2 == -1)return -1;

  Edge* t = g->nodeTable[v1].adj;  
  while(t != NULL && t->idx != v2){
    t = t->link;
  }  if(NULL != t && t->link != NULL){    
  return t->link->idx;
  }  return -1;
}//取得顶点的data值T getVertexValue(GraphLink* g, int i){ 
 if(i == -1)return 0;  return g->nodeTable[i].data;
}//深度遍历void dfs_graph_v(GraphLink* g, int v, bool* visited){  
printf("%c->", getVertexValue(g,v));
  visited[v] = true;  //取得相邻顶点的下标
  int w = get_first_neighbor(g, getVertexValue(g, v));  
  while(w != -1){    
  if(!visited[w]){
      dfs_graph_v(g, w, visited);
    }
    w = get_next_neighbor(g, getVertexValue(g, v), getVertexValue(g,w));
  }
}void dfs_graph(GraphLink* g, T v){ 
 int cnt = g->NumVertices;  
bool* visited = (bool*)malloc(sizeof(bool) * cnt);
  assert(NULL != visited); 
   for(int i = 0; i < cnt; ++i){
    visited[i] =  false;
  }  
  int index = getVertexIndex(g, v);
  dfs_graph_v(g, index, visited);  free(visited);
}//广度遍历void cfs_graph(GraphLink* g, T v){  //创建一个辅助的bool数组,用来识别哪个顶点已经被遍历过了
  int cnt = g->NumVertices; 
   bool* visited = (bool*)malloc(sizeof(bool) * cnt);
  assert(NULL != visited);  
  for(int i = 0; i < cnt; ++i){
    visited[i] =  false;
    
  }  //创建队列
  NodeQueue q;
  init(&q);  //入队
  int tar = getVertexIndex(g, v);
  enQueue(&q, tar);  //队列不为空就执行
  while(length(&q) != 0){    //取得队列的第一个元素
    int ve = getHead(&q)->data;   
     printf("%c->", getVertexValue(g, ve));
    visited[ve] = true;    //出队
    deQueue(&q);

    Edge* e = g->nodeTable[ve].adj;   
     while(NULL != e){      //如果这个顶点没有被遍历过,入队
      if(!visited[e->idx]){
    visited[e->idx] = true;
    enQueue(&q, e->idx);
      }
      e = e->link;
    }
  }
}

graph_linkmain.c

#include "graph_link.h"int main(){
  GraphLink gl;  //初始化图
  init_graph_link(&gl);  //插入节点
  insert_vertex(&gl, 'A');
  insert_vertex(&gl, 'B');
  insert_vertex(&gl, 'C');
  insert_vertex(&gl, 'D');
  insert_vertex(&gl, 'E');
  insert_vertex(&gl, 'F');
  insert_vertex(&gl, 'G');
  insert_vertex(&gl, 'H');

  insert_edge_head(&gl, 'A', 'B');
  insert_edge_head(&gl, 'A', 'C');
  insert_edge_head(&gl, 'B', 'D');
  insert_edge_head(&gl, 'B', 'E');
  insert_edge_head(&gl, 'C', 'F');
  insert_edge_head(&gl, 'C', 'G');
  insert_edge_head(&gl, 'D', 'H');
  insert_edge_head(&gl, 'E', 'H');
  insert_edge_head(&gl, 'F', 'G');  //显示图
  show_graph_link(&gl);  //深度遍历
  dfs_graph(&gl, 'E');  printf("null\n");    
  //广度遍历
  cfs_graph(&gl, 'F');  printf("null\n");
}

完整代码
编译方法:g++ -g nodequeue.c graph_link.c graph_linkmain.c

作者:小石王

原文链接:https://www.cnblogs.com/xiaoshiwang/p/9397645.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消