zoukankan      html  css  js  c++  java
  • 图的遍历-DFS/BFS

    图的遍历
    调试版

    // 基于C语言的图的遍历
    
    #include <stdlib.h>
    #include <stdio.h>
    
    #define MAX_EDGE 15
    #define MAX_SIZE 9
    #define MAX_VERTEX 9
    
    typedef int Edge; // 边
    typedef char Vertex; // 顶点
    
    // 定义图的存储结构 -- 邻接矩阵
    typedef struct {
    	int numV, numE;
    	Edge edge[MAX_EDGE][MAX_EDGE];
    	Vertex vertex[MAX_VERTEX];
    }Graph;
    
    int visited[MAX_VERTEX]; // 访问标记数组 - 未访问:非1, 已访问:1
    
    // 创建图 - 基于邻接矩阵 - 初始化Graph中的变量
    void create_graph(Graph *graph)
    {
    	int i, j;
    
    	graph->numE = 15;
    	graph->numV = 9;
    
    	/* 读入顶点信息,建立顶点表 */
    	graph->vertex[0] = 'A';
    	graph->vertex[1] = 'B';
    	graph->vertex[2] = 'C';
    	graph->vertex[3] = 'D';
    	graph->vertex[4] = 'E';
    	graph->vertex[5] = 'F';
    	graph->vertex[6] = 'G';
    	graph->vertex[7] = 'H';
    	graph->vertex[8] = 'I';
    
    
    	for (i = 0; i < graph->numV; i++)/* 初始化图 */
    	{
    		for (j = 0; j < graph->numV; j++)
    		{
    			graph->edge[i][j] = 0;
    		}
    	}
    
    	graph->edge[0][1] = 1;
    	graph->edge[0][5] = 1;
    
    	graph->edge[1][2] = 1;
    	graph->edge[1][8] = 1;
    	graph->edge[1][6] = 1;
    
    	graph->edge[2][3] = 1;
    	graph->edge[2][8] = 1;
    
    	graph->edge[3][4] = 1;
    	graph->edge[3][7] = 1;
    	graph->edge[3][6] = 1;
    	graph->edge[3][8] = 1;
    
    	graph->edge[4][5] = 1;
    	graph->edge[4][7] = 1;
    
    	graph->edge[5][6] = 1;
    
    	graph->edge[6][7] = 1;
    
    
    	for (i = 0; i < graph->numV; i++)
    	{
    		for (j = i; j < graph->numV; j++)
    		{
    			graph->edge[j][i] = graph->edge[i][j];
    		}
    	}
    }
    
    // 访问一个vertex顶点
    void visit(Graph graph, int index) 
    {
    	printf("%c ", graph.vertex[index]);
    }
    
    
    /******************** 深度遍历 ********************/
    
    void dfs(Graph graph, int index)
    {
    	visited[index] = 1;
    	visit(graph, index);
    
    	for (int i = 0; i < graph.numV; i++)
    		if (graph.edge[index][i] == 1 && !visited)
    			dfs(graph, i);
    }
    
    // 邻接矩阵的DFS
    void dfs_traverse(Graph graph)
    {
    	for (int i = 0; i < graph.numV; i++) // 初始化标记数组为未访问
    		visited[i] = 0;
    	for (int i = 0; i < graph.numV; i++) // 对图的各个连通分量调用DFS, 如果是连通图,则只会执行一次
    		if (!visited[i]) // 根据标记数组,判定vertex是否已经被访问
    			dfs(graph, i);
    }
    
    /******************** 广度遍历 ********************/
    
    typedef struct
    {
    	int data[MAX_SIZE];
    	int front;
    	int rear; 
    }Queue; // 循环队列结构
    
    void create_queue(Queue *queue)
    {
    	queue->front = 0;
    	queue->rear = 0;
    }
    
    int isEmpty(Queue queue)
    {
    	if (queue.front == queue.rear) // 队列是否为空
    		return 1;
    	return 0;
    }
    
    int isFull(Queue queue)
    {
    	if ((queue.rear + 1) % MAX_SIZE == queue.front)
    		return 1;
    	return 0;
    }
    
    // 入队操作 - 入队的是序列号,而非元素Vertex
    void enqueue(Queue *queue, int index)
    {
    	if ((queue->rear + 1) % MAX_SIZE == queue->front) // 队列是否满了
    	{
    		printf("The queue is full.");
    		return;
    	}
    	queue->data[queue->rear] = index; // 存储
    	queue->rear = (queue->rear + 1) % MAX_SIZE; // rear指针后移
    }
    
    // 出队 
    void dequeue(Queue* queue, int* index)
    {
    	if (queue->front == queue->rear) // 队列为空
    		return;
    	*index = queue->data[queue->front]; // 将队头元素出队并赋值给index
    	queue->front = (queue->front + 1) % MAX_SIZE; // front指针后移
    }
    
    void print_queue(Graph graph, Queue queue)
    {
    	printf("queue:");
    	int cursor = queue.front;
    	while (!isEmpty(queue) && cursor != queue.rear)
    	{
    		printf(" %c ", graph.vertex[queue.data[cursor]]);
    		cursor = (cursor + 1) % MAX_SIZE;
    	}
    	printf("
    ");
    }
    
    // 访问某个顶点并入队
    void bfs_visit_vertex(Graph graph, int j, Queue* queue)
    {
    	visited[j] = 1;
    	//visit(graph, j);
    
    
    	printf("入队前:%c  ", graph.vertex[j]);
    	print_queue(graph, *queue);
    	enqueue(queue, j);
    	printf("入队后:");
    	print_queue(graph, *queue);
    	printf("
    ");
    }
    
    void bfs_traverse(Graph graph)
    {
    	Queue queue;
    	create_queue(&queue);
    
    	for (int i = 0; i < graph.numV; i++)
    		visited[i] = 0;
    
    	for (int i = 0; i < graph.numV; i++) // 对每个连通分量做循环 
    	{
    		
    		if (!visited[i]) 
    		{
    			printf("
    ====>%d", i);
    			bfs_visit_vertex(graph, i, &queue); //访问连通分量的第一个邻接点,并入队
    			while (!isEmpty(queue))
    			{
    				printf("出队前:");
    				print_queue(graph, queue);
    				dequeue(&queue, &i); // 将队列中的第一个顶点(序列号)出队
    				printf("出队后:");
    				
    				print_queue(graph, queue);
    				printf("
    ");
    				for (int j = 0; j < graph.numV; j++) // 遍历出队的顶点的所有的邻接点,然后将邻接点全部入队
    				{
    					if (graph.edge[i][j] == 1 && !visited[j]) // 未访问过的邻接点
    					{
    						bfs_visit_vertex(graph, j, &queue);
    					}
    				}
    			}
    		}
    	}
    }
    
    
    int main()
    {
    	Graph graph;
    	create_graph(&graph);
    	printf("
    深度遍历:");
    	dfs_traverse(graph);
    	printf("
    广度遍历:");
    	bfs_traverse(graph);
    	return 0;
    }
    

    最终版

    // 基于C语言的图的遍历
    
    #include <stdlib.h>
    #include <stdio.h>
    
    #define MAX_EDGE 15
    #define MAX_SIZE 9
    #define MAX_VERTEX 9
    
    typedef int Edge; // 边
    typedef char Vertex; // 顶点
    
    // 定义图的存储结构 -- 邻接矩阵
    typedef struct {
    	int numV, numE;
    	Edge edge[MAX_EDGE][MAX_EDGE];
    	Vertex vertex[MAX_VERTEX];
    }Graph;
    
    int visited[MAX_VERTEX]; // 访问标记数组 - 未访问:非1, 已访问:1
    
    // 创建图 - 基于邻接矩阵 - 初始化Graph中的变量
    void create_graph(Graph *graph)
    {
    	int i, j;
    
    	graph->numE = 15;
    	graph->numV = 9;
    
    	/* 读入顶点信息,建立顶点表 */
    	graph->vertex[0] = 'A';
    	graph->vertex[1] = 'B';
    	graph->vertex[2] = 'C';
    	graph->vertex[3] = 'D';
    	graph->vertex[4] = 'E';
    	graph->vertex[5] = 'F';
    	graph->vertex[6] = 'G';
    	graph->vertex[7] = 'H';
    	graph->vertex[8] = 'I';
    
    
    	for (i = 0; i < graph->numV; i++)/* 初始化图 */
    	{
    		for (j = 0; j < graph->numV; j++)
    		{
    			graph->edge[i][j] = 0;
    		}
    	}
    
    	graph->edge[0][1] = 1;
    	graph->edge[0][5] = 1;
    
    	graph->edge[1][2] = 1;
    	graph->edge[1][8] = 1;
    	graph->edge[1][6] = 1;
    
    	graph->edge[2][3] = 1;
    	graph->edge[2][8] = 1;
    
    	graph->edge[3][4] = 1;
    	graph->edge[3][7] = 1;
    	graph->edge[3][6] = 1;
    	graph->edge[3][8] = 1;
    
    	graph->edge[4][5] = 1;
    	graph->edge[4][7] = 1;
    
    	graph->edge[5][6] = 1;
    
    	graph->edge[6][7] = 1;
    
    
    	for (i = 0; i < graph->numV; i++)
    	{
    		for (j = i; j < graph->numV; j++)
    		{
    			graph->edge[j][i] = graph->edge[i][j];
    		}
    	}
    }
    
    // 访问一个vertex顶点
    void visit(Graph graph, int index) 
    {
    	printf("%c ", graph.vertex[index]);
    }
    
    
    /******************** 深度遍历 ********************/
    
    void dfs(Graph graph, int index)
    {
    	visited[index] = 1;
    	visit(graph, index);
    
    	for (int i = 0; i < graph.numV; i++)
    		if (graph.edge[index][i] == 1 && !visited)
    			dfs(graph, i);
    }
    
    // 邻接矩阵的DFS
    void dfs_traverse(Graph graph)
    {
    	for (int i = 0; i < graph.numV; i++) // 初始化标记数组为未访问
    		visited[i] = 0;
    	for (int i = 0; i < graph.numV; i++) // 对图的各个连通分量调用DFS, 如果是连通图,则只会执行一次
    		if (!visited[i]) // 根据标记数组,判定vertex是否已经被访问
    			dfs(graph, i);
    }
    
    /******************** 广度遍历 ********************/
    
    typedef struct
    {
    	int data[MAX_SIZE];
    	int front;
    	int rear; 
    }Queue; // 循环队列结构
    
    void create_queue(Queue *queue)
    {
    	queue->front = 0;
    	queue->rear = 0;
    }
    
    int isEmpty(Queue queue)
    {
    	if (queue.front == queue.rear) // 队列是否为空
    		return 1;
    	return 0;
    }
    
    int isFull(Queue queue)
    {
    	if ((queue.rear + 1) % MAX_SIZE == queue.front)
    		return 1;
    	return 0;
    }
    
    // 入队操作 - 入队的是序列号,而非元素Vertex
    void enqueue(Queue *queue, int index)
    {
    	if ((queue->rear + 1) % MAX_SIZE == queue->front) // 队列是否满了
    	{
    		printf("The queue is full.");
    		return;
    	}
    	queue->data[queue->rear] = index; // 存储
    	queue->rear = (queue->rear + 1) % MAX_SIZE; // rear指针后移
    }
    
    // 出队 
    void dequeue(Queue* queue, int* index)
    {
    	if (queue->front == queue->rear) // 队列为空
    		return;
    	*index = queue->data[queue->front]; // 将队头元素出队并赋值给index
    	queue->front = (queue->front + 1) % MAX_SIZE; // front指针后移
    }
    
    void bfs_traverse(Graph graph)
    {
    	Queue queue;
    	create_queue(&queue);
    
    	for (int i = 0; i < graph.numV; i++)
    		visited[i] = 0;
    
    	for (int i = 0; i < graph.numV; i++) // 对每个顶点做循环 
    	{
    		
    		if (!visited[i]) 
    		{
    			/*printf("
    ====>%d", i);*/
    			visited[i] = 1;
    			visit(graph, i);
    			enqueue(&queue, i);
    			while (!isEmpty(queue))
    			{
    				dequeue(&queue, &i);
    				for (int j = 0; j < graph.numV; j++)
    				{
    					if (graph.edge[i][j] == 1 && !visited[j])
    					{
    						visited[j] = 1;			 
    						visit(graph, j);
    						enqueue(&queue, j);				 
    					}
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    	Graph graph;
    	create_graph(&graph);
    	printf("
    深度遍历:");
    	dfs_traverse(graph);
    	printf("
    广度遍历:");
    	bfs_traverse(graph);
    	return 0;
    }
    
  • 相关阅读:
    curl命令学习笔记
    IOS安全测试思维导图
    Hello World
    Hive SQL使用和数据加载的一点总结
    采用最低松弛度优先调度的实时系统调度程序
    MongoDB Map Reduce速度提升20倍的优化宝典
    释放时间不同可中断平行机问题在线算法
    RPC框架系列——Avro
    Solr 3.6.2索引MySQL数据库配置过程
    IKAnalyzer 独立使用 配置扩展词库
  • 原文地址:https://www.cnblogs.com/neen/p/14031651.html
Copyright © 2011-2022 走看看