图算法(一)

图G=(V, E)是由若干给定的顶点V及连接两顶点的边E所构成的图形,图论起源于柯尼斯堡七桥问题。

1、图的表示

邻接矩阵:表示简单,但是对于稀疏矩阵,浪费空间严重。

邻居表:相对于邻接矩阵,存储复制,稀疏矩阵情况下空间利用率高。以下用邻接表来存储图结构:

 1 struct graph
 2 {
 3     int g_vertexs;
 4     int g_edges;
 5     struct vertex_node *list_head;
 6 };
 7
 8 struct vertex_node
 9 {
10     int vertex;
11     int weight;
12     struct vector_node *next;
13 };

利用文件graph.ini初始化图:

graph.ini:

9 16
0 1 1
0 2 5
1 2 3
1 3 7
1 4 5
2 4 1
2 5 7
3 4 2
3 6 3
4 5 3
4 6 6
4 7 9
5 7 5
6 7 2
6 8 7
7 8 4
 1 void graph_create(struct graph *G, int dir)
 2 {
 3     FILE *fp = fopen("graph.ini", "r");
 4     int i, first, second, weight;
 5     struct vertex_node *node;
 6     if (fp == NULL)
 7     {
 8         perror("fopen");
 9         return;
10     }
11
12     fscanf(fp, "%d %d", &G->g_vertexs, &G->g_edges);
13     G->list_head = (struct vertex_node *)malloc(sizeof(struct vertex_node) * G->g_vertexs);
14     for (i = 0; i < G->g_vertexs; i++)
15     {
16         G->list_head[i].vertex = i;
17         G->list_head[i].weight = 0;
18         G->list_head[i].next = NULL;
19     }
20     for (i = 0; i < G->g_edges; i++)
21     {
22         fscanf(fp, "%d %d %d", &first, &second, &weight);
23         node = (struct vertex_node *)malloc(sizeof(struct vertex_node));
24         node->vertex = second;
25         node->weight = weight;
26         node->next = G->list_head[first].next;
27         G->list_head[first].next = node;
28         if (!dir)
29         {
30             node = (struct vertex_node *)malloc(sizeof(struct vertex_node));
31             node->vertex = first;
32             node->weight = weight;
33             node->next = G->list_head[second].next;
34             G->list_head[second].next = node;
35         }
36     }
37
38     mark = (int *)malloc(sizeof(int) * G->g_vertexs);
39     sp = (int *)malloc(sizeof(int) * G->g_vertexs);
40     pre = (int *)malloc(sizeof(int) * G->g_vertexs);
41     path = (int *)malloc(sizeof(int) * G->g_vertexs);
42 }

图的删除

 1 void graph_destroy(struct graph *G)
 2 {
 3     int i;
 4     struct vertex_node *node;
 5     for (i = 0; i < G->g_vertexs; i++)
 6     {
 7         printf("node = %d", G->list_head[i].vertex);
 8         while (G->list_head[i].next != NULL)
 9         {
10             node = G->list_head[i].next;
11             printf(" -> %d", node->vertex);
12             G->list_head[i].next = node->next;
13             free(node);
14         }
15         printf("\n");
16     }
17     free(G->list_head);
18     free(mark);
19     free(sp);
20     free(pre);
21     free(path);
22 }

2. 图的遍历

深度优先遍历DFS

 1 /* 递归遍历 */
 2 void dfs(struct graph *G, int vertex)
 3 {
 4     struct vertex_node *node;
 5     mark[vertex] = 1;
 6     printf("%d -> ", vertex);
 7     for (node = G->list_head[vertex].next; node != NULL; node = node->next)
 8     {
 9         if (!mark[node->vertex])
10             dfs(G, node->vertex);
11     }
12 }
 1 /* 非递归遍历 */
 2 void dfs(struct graph *G, int vertex)
 3 {
 4     int i;
 5     struct vertex_node *node;
 6     for (i = 0; i < G->g_vertexs; i++)
 7         mark[i] = WHITE;
 8     push(vertex);
 9     while (!stack_empty())
10     {
11         vertex = pop();
12         if (mark[vertex] != BLACK)
13         {
14             mark[vertex] = BLACK;
15             printf("%d -> ", vertex);
16         }
17         for (node = G->list_head[vertex].next; node != NULL; node = node->next)
18         {
19             if (mark[node->vertex] != BLACK)
20             {
21                 push(node->vertex);
22                 mark[node->vertex] = GRAY;
23             }
24         }
25     }
26 }

广度优先遍历BFS

 1 void bfs(struct graph *G, int vertex)
 2 {
 3     struct vertex_node *node;
 4     memset(mark, 0, sizeof(int) * G->g_vertexs);
 5     enqueue(vertex);
 6     while (!queue_empty())
 7     {
 8         vertex = dequeue();
 9         mark[vertex] = 1;
10         printf("%d -> ", vertex);
11         for (node = G->list_head[vertex].next; node != NULL; node = node->next)
12         {
13             if (!mark[node->vertex])
14             {
15                 enqueue(node->vertex);
16                 mark[node->vertex] = 1;
17             }
18         }
19     }
20 }
时间: 2024-10-24 23:29:25

图算法(一)的相关文章

基于mapreducer的图算法

作者系阿里巴巴集团1688技术部普通码农 引言 周末看到一篇不错的文章"Graph Twiddling in a MapReduce world" ,介绍MapReduce下一些图算法的实现.文章语言质朴,介绍很多实用图优化技巧.文章2009年发表,至今已经被引用183次,足以证明这篇文章价值.目前这篇文章网上已经有人对这篇文章做了介绍,但仅介绍了其中最简单的两个算法,对其中的所做优化,并没有做分析.为了加深对文章算法的理解,我重新对这篇文章的算法做了翻译,同时加了自己的理解,以及算法

图算法系列-深度优先搜索与广度优先搜索

2.深度优先搜索 为了访问一个顶点,我们将它标记为已经访问过,然后递归的访问所有与子邻接的并且尚未标记的顶点,这就是深度优先搜索(DFS),DFS常用于解决路径问题. 比如下面的连通图,我们从顶点0开始对图进行探索 下面这个图显示了DFS处理时的递归调用树. DFS可以解决的问题:1)环检测:一个图中有环吗?该图是森林吗?2)简单路径:给定两个顶点,是否存在一条连接他们的路径3)简单连通性:无论何时使用DFS,都可以在线性时间内确定一个图是否连通4)顶点搜索:在给定顶点所在的同一个连通分量中有多

【图算法】综述

from wiki:   图算法 基本遍历 深度优先搜索 · 广度优先搜索 · A* · Flood fill 最短路径 Dijkstra · Bellman-Ford · Floyd-Warshall · Kneser图 最小生成树 Prim · Kruskal 强连通分量 Kosaraju算法 · Gabow算法 · Tarjan算法 图匹配 匈牙利算法 · Hopcroft–Karp · Edmonds's matching 网络流 Ford-Fulkerson · Edmonds-Kar

【每日算法】图算法(遍历&amp;MST&amp;最短路径&amp;拓扑排序)

图有邻接矩阵和邻接表两种存储方法,邻接矩阵很简单,这里不讨论,下面我们先看看常用的邻接表表示方法. 邻接表常用表示方法 指针表示法 指针表示法一共需要两个结构体: struct ArcNode //定义边表结点 { int adjvex: //邻接点域 ArcNode* next; }; struct VertexNode //定义顶点表结点 { int vertex; ArcNode* firstedge; }; 每个节点对应一个VertexNode,其firstedge指向边表(与当前节点邻

Program in Lua中图算法的改进(打印所有图路径)

在Program in Lua第二版,第11.7节中介绍了用lua写"图"数据结构的方法, 但书中提供的图的算法只能打印出第一条找到的正确路径,于是我就自己琢磨 着怎么用lua写出一个图算法打印出所有可能的路径,自己独自一个人思考了 很久,期间没有参考任何资料,完全靠"头脑暴力"把它解决了,最后思考了看看, 也不知道这到底是什么算法,完全凭借着自己认为的所谓的"退化"的概念,奇妙 的解决了这个问题,所以我把这个算法拿出来分享一下. (总觉得在哪本

图算法

图论问题对计算机科学至关重要,这个我认同,遇到很多的问题都可以归结为图论问题. 图本身是解决连接问题的模型,现实世界中的很多问题都可以用图来建模. 比如说网络,网络对于计算机的重要性不言而喻,图算法可以用来求解很多的网络问题. 树结构可以看成是一种简化的图 图的表示 图的广度优先搜索和深度优先搜索 最小生成树 两结点之间最短路径 网络最大流的计算

图算法(1):Dijkstra&#39;s algorithm

Dijkstra's algorithm使用了广度优先搜索解决非负权图的单源最短路径问题,算法最终得到一个最短路径树.该算法常用于路由算法或者作为其他图算法的一个子模块.举例来说,如果图中的顶点表示城市,而边上的权重表示著城市间开车行经的距离,该算法可以用来找到两个城市之间的最短路径. 其基本原理是:每次新扩展一个距离最短的点,更新与其相邻的点的距离.当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性.不过根据这个原理,用Dijk

基于OpenCL的图像积分图算法改进

复杂的算法却未必低效,简单的算法往往要付出代价,这个代价可能很大.在opencl环境下编程,与我们在CPU上的传统编程思想有一些差异,这些差异看似微不足道,但往往是细节决定成功,就是这些看似微不足道的差异,在多核的GPU上被无限放大,导致同一种算法在GPU和CPU运行效果有着巨大的差别. 之前写过一篇文章<基于OpenCL的图像积分图算法实现>介绍了opencl中积分图算法的基本原理(不了解积分图概念的朋友可以先参考这篇文章),并基于这个基本原理提供了kernel实现代码.但经过这两个月的实践

[blog]基于卷积神经网络的以图搜图算法实现

基于卷积神经网络的以图搜图算法实现        如果用这个名称去搜索论文,一定有不少.为什么了,因为从原理上来看,卷积神经网络就非常适合找图片的相似的地方.想想看,许多大牛.小牛.微牛的文章都是说如何从mnist中.从CIFA10中.从CIFA100中去找到相似的图片.那么,反过来想一想,如果那么复杂的数据卷积神经网络都能够去处理,那么对于这种相对来说,比较简单的"以图搜图"的需求,应该更容易来解决.这里的神经网络解决这个问题,还是尝试得到一种较为通用的问题解决方法. 零.数据集的创

图算法系列-图的简单实现

最近看了很多介绍图算法的文章,发现网上可以搜到的资料比较少,所以打算在这写一个介绍图算法的系列文章,一方面是帮助自己整理,另一方面也给大家分享下这方面的知识. 1.1图的定义: 图(graph)由顶点(vertex)和边(edge)的集合组成,每一条边就是一个点对(v,w). 图的种类:地图,电路图,调度图,事物,网络,程序结构 图的属性:有V个顶点的图最多有V*(V-1)/2条边 1.2图的ADT: 1 struct Edge{ 2 int v,w; 3 Edge(int a=-1,int b