数据结构8-图的遍历

1.BFS:广度优先(breadth  first  search)(队列)

1.1基于邻接矩阵的广度优先

queue.h

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include <stdio.h>

#define SIZE 512
//函数声明
int is_empty(void);
int is_full(void);
void enqueue(int c);
int dequeue(void);

extern int queue[SIZE]; // 便于另一个.c代码使用

#endif

queue.c

#include "queue.h"

int queue[SIZE];

int head = 0, tail = 0;

//循环队列入队
void enqueue(int n)
{
	queue[tail] = n;
	tail = (tail+1) % SIZE;
}
//出队
int dequeue(void)
{
	int n;
	n = queue[head];
	head = (head + 1) % SIZE;
        return n;
}
//判断队列是否为空
int is_empty(void)
{
	return head == tail;
}
//判断队列为满
int is_full(void)
{
        return (tail + 1) % SIZE == head;
}

DFS_AMG.c

#include <stdio.h>
#include <stdlib.h>
#include "queue.h"  //包含队列
#define MAX 100



// 邻接矩阵的图 
struct AMG_Graph
{
     int vex_num, edge_num;    // 顶点个数,边个数
     char Vex[MAX];            // 顶点信息(一维数组)
     int Edge[MAX][MAX];       // 顶点关系信息 0/1(二维数组)
};

//函数声明
struct AMG_Graph *Creat_AMG_Graph(void);
void Show_AMG_Graph(struct AMG_Graph *graph);
int search_vex(struct AMG_Graph *graph, char c);
void BFS_AMG(struct AMG_Graph *graph);

// 主函数
int main(void)
{
    struct AMG_Graph *d_graph;     // 有向图指针
    d_graph = Creat_AMG_Graph();   // 创建邻接矩阵    
    Show_AMG_Graph(d_graph);

    printf("traverse the graph through BFS:\n");
    BFS_AMG(d_graph);           // 广度优先邻接矩阵有向图      
    return 0;
}


struct AMG_Graph *Creat_AMG_Graph(void)
{
     int i,j;
     char u,v;
     struct AMG_Graph *graph;
     graph = (struct AMG_Graph *)malloc(sizeof(struct AMG_Graph));
     printf("please enter the number of vex: ");
     scanf("%d", &graph->vex_num);
     printf("please enter the number of edge: ");
     scanf("%d", &graph->edge_num);
      
     while(getchar() != '\n');  // 消灭回车

     printf("please enter the vertex:\n");
     for(i = 0; i < graph->vex_num; i++)
     {
           graph->Vex[i] = getchar();
           while(getchar() != '\n');
     }
     // 初始化二维数组
     for(i = 0; i < graph->vex_num; i++)
     {
          for(j = 0; j < graph->vex_num; j++)
               graph->Edge[i][j] = 0;
     }
    
     // 输入顶点
     while(graph->edge_num--)
     {
          printf("please enter the vex that connect each other by edge:\n");
          u = getchar();
          while(getchar() != '\n');
          v = getchar();
          while(getchar() != '\n'); 
          
          i = search_vex(graph, u);
          j = search_vex(graph, v);
          
          if(i != -1 && j != -1)
                  //graph->Edge[i][j] = graph->Edge[j][i] = 1; // 无向图
                  graph->Edge[i][j] = 1;                     // 有向图 唯一区别
          else  
          {
                  printf("wrong vex, enter again.\n");
                  graph->edge_num++;
          }
     }
     return graph;
}

// 显示
void Show_AMG_Graph(struct AMG_Graph *graph)
{
     int i,j;
     printf("show the vertex:\n");
     for(i = 0; i < graph->vex_num; i++)
          printf("%c ", graph->Vex[i]);
     printf("\n");
 
     printf("show the adjacency matrices:\n");
     for(i = 0; i < graph->vex_num; i++)
     {
          for(j = 0; j < graph->vex_num; j++)
               printf("%d\t", graph->Edge[i][j]);
          printf("\n");
     }
      
}

// 查找位置
int search_vex(struct AMG_Graph *graph, char c)
{
      int i; 
      for(i = 0; i < graph->vex_num; i++)
      {
          if(c == graph->Vex[i])
             return i;  
      } 
      return -1;
}

// 广度优先邻接矩阵有向图   
void BFS_AMG(struct AMG_Graph *graph)
{
     int u;
     int i,j;
     int visited[MAX] = {0};
     for(j = 0; j < graph->vex_num; j++)  // 非连通
     {
        if(visited[j] == 0)
        {
           printf("%c ", graph->Vex[j]);
           visited[j] = 1;
           enqueue(j);
   
           while(!is_empty())
           {
               u = dequeue();
               for(i = 0; i < graph->vex_num; i++)
               {
                   if(graph->Edge[u][i] == 1 && visited[i] == 0)
                   {
                      visited[i] = 1;
                      enqueue(i); 
                      printf("%c ",graph->Vex[i]);
                  } 
              }
          }
       }
    }
     printf("\n");
}

有向图输出结果

 无向图输出结果

1.2基于邻接表的广度优先

queue.h    queue.c 相同

BFS_ALG.c

#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
#define MAX 100

//邻接点表
struct AdjNode
{
     int index;
     struct AdjNode *next;
};

//节点表
struct VexNode
{
     char node;
     struct AdjNode *first;
};

//邻接表
struct ALG_Graph
{
     int vex_num, edge_num;    // 顶点个数,边个数
     struct VexNode Vex[MAX];  // 节点信息
};

struct ALG_Graph *Create_ALG_Graph(void);
int search_vex(struct ALG_Graph *graph, char c);
void  create_adj_node_list(struct ALG_Graph *graph, int i, int j);
void Show_ALG_Graph(struct ALG_Graph *graph);
void BFS_ALG(struct ALG_Graph *graph);

// 主函数
int main(void)
{
        struct ALG_Graph *d_graph;
        d_graph = Create_ALG_Graph();
        Show_ALG_Graph(d_graph);

        printf("traverse the graph through BFS:\n");
        BFS_ALG(d_graph);           // 广度优先邻接表有向图 
        return 0;
}

// 节点表
struct ALG_Graph *Create_ALG_Graph(void)
{
        int i, j;
        char u, v;
        struct ALG_Graph *graph;       
        graph = (struct ALG_Graph *)malloc(sizeof(struct ALG_Graph));

        printf("please enter the number of vex: ");
        scanf("%d", &graph->vex_num);
        printf("please enter the number of edge: ");
        scanf("%d", &graph->edge_num);
        while(getchar() != '\n');  // 消灭回车

        //节点信息
        printf("please enter the vertex:\n");
        for(i = 0; i < graph->vex_num; i++)
        {
              graph->Vex[i].node = getchar();
              while(getchar() != '\n');
        }
        //指针部分设为空
        for(i = 0; i < graph->vex_num; i++)
        {
              graph->Vex[i].first = NULL;
        }
        
        // 输入顶点信息
        while(graph->edge_num--)
        {
             printf("please enter the vex that connect each other by edge:\n");
             u = getchar();
             while(getchar() != '\n');
             v = getchar();
             while(getchar() != '\n'); 
             
             i = search_vex(graph, u);
             j = search_vex(graph, v);
             
             if(i != -1 && j != -1)
                    create_adj_node_list(graph, i, j);    // 创建邻接点表
             else
             {
                    printf("wrong vex, enter again.\n");
                    graph->edge_num++;
             }        
       }
       return graph;
}

// 创建邻接点表(重点)
void create_adj_node_list(struct ALG_Graph *graph, int i, int j)
{
        struct AdjNode *s = (struct AdjNode *)malloc(sizeof(struct AdjNode));
        s->index = j;    
        s->next = graph->Vex[i].first;
        graph->Vex[i].first = s;
}

// 查找位置
int search_vex(struct ALG_Graph *graph, char c)
{
        int i; 
        for(i = 0; i < graph->vex_num; i++)
        {
             if(c == graph->Vex[i].node)
                    return i;  
        } 
        return -1;
}

// 显示
void Show_ALG_Graph(struct ALG_Graph *graph)
{
        int i;
        struct AdjNode *t;

        printf("show the ALG Graph:\n"); 
        for(i = 0; i < graph->vex_num; i++) 
        {
             printf("%c: ", graph->Vex[i].node);
             t = graph->Vex[i].first;
             while(t != NULL)
             {
                  printf("%d ", t->index);
                  t = t->next;
             }
             printf("\n");
        } 
        
}

// 广度优先邻接表有向图   
void BFS_ALG(struct ALG_Graph *graph)
{
     int u;
     int n;
     int i;
     struct AdjNode *p;
     int visited[MAX] = {0};      
     for(i = 0; i < graph->vex_num; i++)  // 非连通
     {
        if(visited[i] == 0)
        {
            printf("%c ", graph->Vex[i].node);
            visited[i] = 1;
            enqueue(i);
   
            while(!is_empty())     // 队列不为空
            {
                 u = dequeue();    // 编号出队列
                 p = graph->Vex[u].first;
                 while(p)
                 {
                       n = p->index;
                       if(visited[n] == 0)
                       {
                           visited[n] = 1;
                           enqueue(n);
                           printf("%c ", graph->Vex[n].node);
                       }
                       p = p->next;
                 }
            }            
        }
      }
      printf("\n");
}

2.DFS深度优先(栈)

2.1基于邻接矩阵的深度优先

stack.h

#ifndef __STACK_H__
#define __STACK_H__

#include <stdio.h>

extern int stack[512];
extern int top;

void push(int c);
int pop(void);
int is_empty(void);

#endif

stack.c

扫描二维码关注公众号,回复: 15954733 查看本文章
#include "stack.h"

int stack[512];
int top = 0;
//入栈
void push(int c)
{
	stack[top++] = c;
}
//出栈
int pop(void)
{
	return stack[--top];
}
//判断是否为空
int is_empty(void)
{
	return top == 0;
}

DFS_AMG.c 

#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

#define MAX 100
int stack[512];
// 邻接矩阵的图 
struct AMG_Graph
{
     int vex_num, edge_num;    // 顶点个数,边个数
     char Vex[MAX];            // 顶点信息(一维数组)
     int Edge[MAX][MAX];       // 顶点关系信息 0/1(二维数组)
};

//函数声明
struct AMG_Graph *Creat_AMG_Graph(void);
void Show_AMG_Graph(struct AMG_Graph *graph);
int search_vex(struct AMG_Graph *graph, char c);
void DFS_AMG(struct AMG_Graph *graph);

// 主函数
int main(void)
{
    struct AMG_Graph *d_graph;     // 有向图指针
    d_graph = Creat_AMG_Graph();   // 创建邻接矩阵    
    Show_AMG_Graph(d_graph);

    printf("traverse the graph through DFS:\n");
    DFS_AMG(d_graph);           // 深度优先邻接矩阵有向图 
    return 0;
}


// 
struct AMG_Graph *Creat_AMG_Graph(void)
{
     int i,j;
     char u,v;
     struct AMG_Graph *graph;
     graph = (struct AMG_Graph *)malloc(sizeof(struct AMG_Graph));
     printf("please enter the number of vex: ");
     scanf("%d", &graph->vex_num);
     printf("please enter the number of edge: ");
     scanf("%d", &graph->edge_num);
      
     while(getchar() != '\n');  // 消灭回车

     printf("please enter the vertex:\n");
     for(i = 0; i < graph->vex_num; i++)
     {
           graph->Vex[i] = getchar();
           while(getchar() != '\n');
     }
     // 初始化二维数组
     for(i = 0; i < graph->vex_num; i++)
     {
          for(j = 0; j < graph->vex_num; j++)
               graph->Edge[i][j] = 0;  // 有向图
     }
    
     // 输入顶点
     while(graph->edge_num--)
     {
          printf("please enter the vex that connect each other by edge:\n");
          u = getchar();
          while(getchar() != '\n');
          v = getchar();
          while(getchar() != '\n'); 
          
          i = search_vex(graph, u);
          j = search_vex(graph, v);
          
          if(i != -1 && j != -1)
                  graph->Edge[i][j] = 1;
          else
          {
                  printf("wrong vex, enter again.\n");
                  graph->edge_num++;
          }
     }
     return graph;
}

// 显示
void Show_AMG_Graph(struct AMG_Graph *graph)
{
     int i,j;
     printf("show the vertex:\n");
     for(i = 0; i < graph->vex_num; i++)
          printf("%c ", graph->Vex[i]);
     printf("\n");
 
     printf("show the adjacency matrices:\n");
     for(i = 0; i < graph->vex_num; i++)
     {
          for(j = 0; j < graph->vex_num; j++)
               printf("%d\t", graph->Edge[i][j]);
          printf("\n");
     }
      
}

// 查找位置
int search_vex(struct AMG_Graph *graph, char c)
{
      int i; 
      for(i = 0; i < graph->vex_num; i++)
      {
          if(c == graph->Vex[i])
             return i;  
      } 
      return -1;
}


void DFS_AMG(struct AMG_Graph *graph)
{  
      int i, j;
      int u;

      int visited[MAX] = {0};
      for(i = 0; i < graph->vex_num; i++)       // 防止非连通图漏掉点
      {
            if(visited[i] == 0)                 // 没有访问
            {
                  printf("%c ", graph->Vex[i]);
                  visited[i] = 1;
                  push(i);

                  while(!is_empty())
                  {
                       u = stack[top-1];        // 访问栈顶内容
                       for(j = 0; j < graph->vex_num; j++)                    
                       {
                            if((graph->Edge[u][i] == 1) && (visited[i] == 0))
                            {
                                  visited[i] = 1;
                                  push(j); 
                                  printf("%c ",graph->Vex[j]);
                                  break;        // 关键
                            }                                                  
                       }
                       if(j == graph->vex_num)  // 访问到头没有满足条件的
                            pop();              // 出栈
                  }
            }
      }
      printf("\n");
}

// 输出 a b c d e f g

2.2 基于邻接表的深度优先

stack.h

#ifndef __STACK_H__
#define __STACK_H__

#include <stdio.h>

extern int stack[512];
extern int top;

void push(int c);
int pop(void);
int is_empty(void);

#endif

stack.c

#include "stack.h"

int stack[512];
int top = 0;
//入栈
void push(int c)
{
	stack[top++] = c;
}
//出栈
int pop(void)
{
	return stack[--top];
}
//判断是否为空
int is_empty(void)
{
	return top == 0;
}

DFS_ALG.c

#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

#define MAX 100

//邻接点表
struct AdjNode
{
     int index;
     struct AdjNode *next;
};

//节点表
struct VexNode
{
     char node;
     struct AdjNode *first;
};

//邻接表
struct ALG_Graph
{
     int vex_num, edge_num;    // 顶点个数,边个数
     struct VexNode Vex[MAX];  // 节点信息
};

struct ALG_Graph *Create_ALG_Graph(void);
int search_vex(struct ALG_Graph *graph, char c);
void  create_adj_node_list(struct ALG_Graph *graph, int i, int j);
void Show_ALG_Graph(struct ALG_Graph *graph);
void DFS_ALG(struct ALG_Graph *graph);

// 主函数
int main(void)
{
        struct ALG_Graph *d_graph;    // 有向图
        d_graph = Create_ALG_Graph();
        Show_ALG_Graph(d_graph);

        printf("traverse the graph through DFS:\n");
        DFS_ALG(d_graph);             // 深度优先邻接表有向图 
        return 0;
}

// 节点表
struct ALG_Graph *Create_ALG_Graph(void)
{
        int i, j;
        char u, v;
        struct ALG_Graph *graph;       
        graph = (struct ALG_Graph *)malloc(sizeof(struct ALG_Graph));

        printf("please enter the number of vex: ");
        scanf("%d", &graph->vex_num);
        printf("please enter the number of edge: ");
        scanf("%d", &graph->edge_num);
        while(getchar() != '\n');  // 消灭回车

        //节点信息
        printf("please enter the vertex:\n");
        for(i = 0; i < graph->vex_num; i++)
        {
              graph->Vex[i].node = getchar();
              while(getchar() != '\n');
        }
        //指针部分设为空
        for(i = 0; i < graph->vex_num; i++)
        {
              graph->Vex[i].first = NULL;
        }
        
        // 输入顶点信息
        while(graph->edge_num--)
        {
             printf("please enter the vex that connect each other by edge:\n");
             u = getchar();
             while(getchar() != '\n');
             v = getchar();
             while(getchar() != '\n'); 
             
             i = search_vex(graph, u);
             j = search_vex(graph, v);
             
             if(i != -1 && j != -1)
                    create_adj_node_list(graph, i, j);    // 创建邻接点表
             else
             {
                    printf("wrong vex, enter again.\n");
                    graph->edge_num++;
             }        
       }
       return graph;
}

// 创建邻接点表(重点)
void create_adj_node_list(struct ALG_Graph *graph, int i, int j)
{
        struct AdjNode *s = (struct AdjNode *)malloc(sizeof(struct AdjNode));
        s->index = j;    
        s->next = graph->Vex[i].first;
        graph->Vex[i].first = s;
}

// 查找位置
int search_vex(struct ALG_Graph *graph, char c)
{
        int i; 
        for(i = 0; i < graph->vex_num; i++)
        {
             if(c == graph->Vex[i].node)
                    return i;  
        } 
        return -1;
}

// 显示
void Show_ALG_Graph(struct ALG_Graph *graph)
{
        int i;
        struct AdjNode *t;

        printf("show the ALG Graph:\n"); 
        for(i = 0; i < graph->vex_num; i++) 
        {
             printf("%c: ", graph->Vex[i].node);
             t = graph->Vex[i].first;
             while(t != NULL)
             {
                  printf("%d ", t->index);
                  t = t->next;
             }
             printf("\n");
        } 
        
}

// 广度优先邻接表有向图   
void DFS_ALG(struct ALG_Graph *graph)
{
     int u;
     int n;
     int i;

     struct AdjNode *p;
     int visited[MAX] = {0};
      
     for(i = 0; i < graph->vex_num; i++)  // 非连通
     {
        if(visited[i] == 0)
        {
            printf("%c ", graph->Vex[i].node);
            visited[i] = 1;
            push(i);
   
            while(!is_empty())     // 栈不为空
            {
                 u = stack[top-1];        // 获取栈顶编号
                 p = graph->Vex[u].first;
                 while(p)
                 {
                       n = p->index;
                       if(visited[n] == 0)
                       {
                           visited[n] = 1;
                           push(n);
                           printf("%c ", graph->Vex[n].node);
                           p = graph->Vex[n].first;
                       }
                       else                     
                           p = p->next; // 遇见访问过的跳过
                 }
                 pop();  // 遇到空指针出栈
            }            
        }
     }
     printf("\n");
}

3.插点法(floyd法)

寻找最短路径

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAX 100

// 邻接矩阵的图 
struct AMG_Graph
{
     int vex_num, edge_num;    // 顶点个数,边个数
     char Vex[MAX];            // 顶点信息(一维数组)
     int Edge[MAX][MAX];       // 顶点关系信息 0/1(二维数组)
};

// 函数声明
struct AMG_Graph *Creat_AMG_Graph(void); 
void Show_AMG_Graph_dist_p(struct AMG_Graph *graph);   // 显示
int search_vex(struct AMG_Graph *graph, char c);       // 寻找二维矩阵点
void Floyd(struct AMG_Graph *graph);                   // 算法

// 两个二维矩阵声明
double dist[MAX][MAX];     // 权重图
int p[MAX][MAX];           // 前驱点图

// 主函数
int main(void)
{
    struct AMG_Graph *d_graph;       // 有向图指针
    char start, end;
    int s, e;

    d_graph = Creat_AMG_Graph();     // 创建邻接矩阵    
    Show_AMG_Graph_dist_p(d_graph);
    
    // 寻找最短路径并显示
    Floyd(d_graph);
    printf("\n\nNow show the shortest distance matrix:\n");
    Show_AMG_Graph_dist_p(d_graph);

    // 验证寻找点之间最短距离
    printf("please enter the start and end point:\n");
    scanf("%c %c", &start, &end);
    s = search_vex(d_graph, start);
    e = search_vex(d_graph, end);
    printf("the shortest distance between %c and %c is %.1f.\n", start, end, dist[s][e]);
    
    return 0;
}


// 创建
struct AMG_Graph *Creat_AMG_Graph(void)
{
     int i,j;
     char u,v;
     double l;

     struct AMG_Graph *graph;
     graph = (struct AMG_Graph *)malloc(sizeof(struct AMG_Graph));
     printf("please enter the number of vex: ");
     scanf("%d", &graph->vex_num);
     printf("please enter the number of edge: ");
     scanf("%d", &graph->edge_num);
      
     while(getchar() != '\n');  // 消灭回车
     
     printf("please enter the vertex:\n");
     for(i = 0; i < graph->vex_num; i++)
     {
           graph->Vex[i] = getchar();
           while(getchar() != '\n');
     }
     // 初始化二维数组
     for(i = 0; i < graph->vex_num; i++)
     {
          for(j = 0; j < graph->vex_num; j++)
          {
               graph->Edge[i][j] = 0;

               // 初始化dist[i][j]
               if(i == j)
                     dist[i][j] = 0;
               else
                     dist[i][j] = INFINITY;   //无穷大

               // 前驱点初始化为-1
                p[i][j] = -1;
          }
     }
    
     // 输入顶点
     while(graph->edge_num--)
     {
          // 输入有关的两点
          printf("please enter the vex that connect each other by edge:\n");
          u = getchar();
          while(getchar() != '\n');
          v = getchar();
          while(getchar() != '\n'); 

          // 输入两点距离(权重)
          printf("please enter the distance between the two vex:\n");
          scanf("%lf", &l);
          while(getchar() != '\n'); 

          // 查找两点位置数值
          i = search_vex(graph, u);
          j = search_vex(graph, v);
          
          // 将dist数组填入权重
          if(i != -1 && j != -1)
          {
                  graph->Edge[i][j] = 1;  // 邻接矩阵
                  dist[i][j] = l;         // 距离
                  p[i][j] = i;            // 前驱
          }
          else
          {
                  printf("wrong vex, enter again.\n");
                  graph->edge_num++;
          }
     }
     return graph;
}

// 显示
void Show_AMG_Graph_dist_p(struct AMG_Graph *graph)
{
     int i,j;
     // 显示顶点
     printf("show the vertex:\n");
     for(i = 0; i < graph->vex_num; i++)
          printf("%c ", graph->Vex[i]);
     printf("\n");

     //显示邻接矩阵
     printf("show the adjacency matrices:\n");
     for(i = 0; i < graph->vex_num; i++)
     {
          for(j = 0; j < graph->vex_num; j++)
               printf("%d\t", graph->Edge[i][j]);
          printf("\n");
     }

     // 显示距离权重矩阵
     printf("show the distance matrices:\n");
     for(i = 0; i < graph->vex_num; i++)
     {
          for(j = 0; j < graph->vex_num; j++)
               printf("%.1f\t", dist[i][j]);
          printf("\n");
     }

     // 显示前驱矩阵
     printf("show the pre point matrices:\n");
     for(i = 0; i < graph->vex_num; i++)
     {
          for(j = 0; j < graph->vex_num; j++)
               printf("%d\t", p[i][j]);
          printf("\n");
     }
      
}

// 查找位置
int search_vex(struct AMG_Graph *graph, char c)
{
      int i; 
      for(i = 0; i < graph->vex_num; i++)
      {
          if(c == graph->Vex[i])
             return i;  
      } 
      return -1;
}

// floyd 算法
void Floyd(struct AMG_Graph *graph)
{
      int k, i, j;
      for(k = 0; k < graph->vex_num; k++)  // 大循环a b c d,分别以a b c d 为插入点
      {
           for(i = 0; i < graph->vex_num; i++)
           {
                 for(j = 0; j < graph->vex_num; j++)  // 遍历dist矩阵 
                 {
                       if(dist[i][j] > dist[i][k] + dist[k][j])
                       { 
                             dist[i][j] = dist[i][k] + dist[k][j]; // 更新dist
                             p[i][j] = p[k][j];                    // 更新前驱矩阵
                       }
                 }
           }
      }
}

猜你喜欢

转载自blog.csdn.net/qq_44177768/article/details/127739469