图通常有两种表示方法: 邻接矩阵 和 邻接表

对于稀疏的图,邻接表表示能够极大地节省空间。

以下是图的数据结构的主要部分:

struct Vertex{

ElementType element; //节点的名字

Edge *next;   //所包含的边组成的单链表的头指针

};

struct Edge{

int adj;  //节点的标号(0-number of nodes)

Edge *next;

};

注意,实际应用中,节点都有名字,而不是数字,所以我们需要提供从名字到标号的映射。

最简单的方法就是 Hash(散列表),或者二叉查找树之类的能够快速提供查询的数据结构。

本文的处理较为简单: 节点的名字是 'a' ---- 'z', 所以映射通过简单的运算即可实现:   node id = node name - 'a'.

  1. // copyright @ L.J.SHOU Jan.13, 2014
  2.  
  3. #include "graph.h"
  4. #include <ctime>
  5. #include <iostream>
  6. #include <stack>
  7. #include <queue>
  8. using namespace std;
  9.  
  10. typedef char ElementType;
  11. typedef Vertex* Graph;
  12.  
  13. enum Color{WHITE, GRAY, BLACK};
  14.  
  15. struct Edge
  16. {
  17. int vertex;
  18. int weight;
  19. Edge *next;
  20. };
  21.  
  22. struct Vertex
  23. {
  24. Color color;
  25. ElementType element;
  26. int start, finish;
  27. Edge *next;//head of adjacent list
  28. };
  29.  
  30. Graph Create(Graph graph, int n)
  31. {
  32. graph = new Vertex[n];
  33. for(int i=0; i<n; ++i)
  34. {
  35. graph[i].color = WHITE;
  36. graph[i].element = i + 'a';
  37. graph[i].start = 0;
  38. graph[i].finish = 0;
  39. graph[i].next = NULL;
  40. }
  41. return graph;
  42. }
  43.  
  44. // Reset Graph
  45. void Clear(Graph graph, int n)
  46. {
  47. for(int i=0; i<n; ++i)
  48. {
  49. graph[i].color = WHITE;
  50. graph[i].start = 0;
  51. graph[i].finish = 0;
  52. }
  53. }
  54.  
  55. Graph DeleteGraph(Graph graph, int n)
  56. {
  57. for(int i=0; i<n; ++i)
  58. {
  59. Edge* head(graph[i].next), *next(NULL);
  60. while(head)
  61. {
  62. next = head->next;
  63. delete head;
  64. head = next;
  65. }
  66. }
  67. delete [] graph;
  68. return NULL;
  69. }
  70.  
  71. // return the outdegree of vertex i
  72. int OutDegree(Graph g, int i)
  73. {
  74. int num(0);
  75.  
  76. Edge* link(g[i].next);
  77. while(link)
  78. {
  79. link = link->next;
  80. ++ num;
  81. }
  82. return num;
  83. }
  84.  
  85. // test whether edge(i, j) exists
  86. bool Exist(Graph g, int i, int j)
  87. {
  88. Edge *link(g[i].next);
  89.  
  90. while(link && link->vertex != j)
  91. link = link->next;
  92.  
  93. if(link == NULL)
  94. return false;
  95. else
  96. return true;
  97. }
  98.  
  99. bool InsertEdge(Graph g, int i, int j)
  100. {
  101. if(Exist(g, i, j)){
  102. cout << "edge (" << i << "," << j << ") already existed" << endl;
  103. return false;
  104. }
  105.  
  106. Edge *edge(NULL);
  107. edge = new struct Edge;
  108. edge->vertex = j;
  109. edge->next = g[i].next;
  110. g[i].next = edge;
  111.  
  112. return true;
  113. }
  114.  
  115. bool DeleteEdge(Graph g, int i, int j)
  116. {
  117. if(!Exist(g, i, j)){
  118. cout << "edge (" << i << "," << j << ") doesn't exist" << endl;
  119. return false;
  120. }
  121.  
  122. Edge *cur(g[i].next), *pre(cur);
  123.  
  124. while(cur && cur->vertex != j)
  125. {
  126. pre = cur;
  127. cur = cur->next;
  128. }
  129.  
  130. if(pre == NULL)
  131. { // delete head edge
  132. g[i].next = cur->next;
  133. delete cur;
  134. }
  135. else
  136. {
  137. pre->next = cur->next;
  138. delete cur;
  139. }
  140. return true;
  141. }
  142.  
  143. // print adjacent list
  144. void OutPut(Graph g, int n)
  145. {
  146. Edge *edge(NULL);
  147. for(int i=0; i<n; ++i)
  148. {
  149. cout << g[i].element << "->";
  150. edge = g[i].next;
  151. while(edge)
  152. {
  153. cout << g[edge->vertex].element << "->";
  154. edge = edge->next;
  155. }
  156. cout << "NULL" << endl;
  157. }
  158. }
  159.  
  160. void DFS(Graph graph, int n)
  161. {
  162. cout << "DFS: " << endl;;
  163. Clear(graph, n);
  164. for(int i=0; i<n; ++i)
  165. {
  166. if(graph[i].color == WHITE)
  167. DFSVisit(graph, i);
  168. }
  169. cout << endl;
  170.  
  171. cout << "DFS_stack: " << endl;
  172. Clear(graph, n);
  173. for(int i=0; i<n; ++i)
  174. {
  175. if(graph[i].color == WHITE)
  176. DFSVisitStack(graph, i);
  177. }
  178. cout << endl;
  179. }
  180.  
  181. // recursive DFS
  182. void DFSVisit(Graph graph, int i)
  183. {
  184. static int time(0);
  185. Edge *link(graph[i].next);
  186.  
  187. cout << graph[i].element << " ";
  188. graph[i].color = GRAY;
  189. graph[i].start = ++time;
  190.  
  191. while(link)
  192. {
  193. if(graph[link->vertex].color == WHITE)
  194. DFSVisit(graph, link->vertex);
  195. link = link->next;
  196. }
  197.  
  198. graph[i].finish = ++time;
  199. graph[i].color = BLACK;
  200. }
  201.  
  202. // non-recursive DFS
  203. void DFSVisitStack(Graph g, int i)
  204. {
  205. static int time(0);
  206. struct Edge* edge;
  207. int vertex;
  208. stack<int> s;
  209.  
  210. //visit vertex i
  211. cout << g[i].element << " ";
  212. g[i].color = GRAY;
  213. g[i].start = ++time;
  214. s.push(i);
  215.  
  216. while(!s.empty())
  217. {
  218. vertex = s.top();
  219. edge = g[vertex].next;
  220. while(edge)
  221. {
  222. if(g[edge->vertex].color == WHITE)
  223. {
  224. s.push(edge->vertex);
  225. cout << g[edge->vertex].element << " ";
  226. g[edge->vertex].start = ++time;
  227. g[edge->vertex].color = GRAY;
  228. break;
  229. }
  230. edge = edge->next;
  231. }
  232. //vertex's neigbours have been visited
  233. if(edge == NULL){
  234. s.pop();
  235. g[vertex].color = BLACK;
  236. g[vertex].finish = ++time;
  237. }
  238. }
  239. }
  240.  
  241. /////////////////////////////////////////////////////////////
  242. // search all vertices that can be rearched from Source s ///
  243. // compute the distances from source s /// ///////////////
  244. /////////////////////////////////////////////////////////////
  245. void BFS(Graph g, int n, int s)
  246. {
  247. queue<int> q;
  248. Edge *edge(NULL);
  249. int vertex;
  250.  
  251. //visit source vertex
  252. Clear(g, n);
  253. cout << "BFS: " << endl;;
  254. cout << g[s].element << " ";
  255. g[s].color = GRAY;
  256. q.push(s);
  257.  
  258. while(!q.empty())
  259. {
  260. //dequeue
  261. vertex = q.front();
  262. q.pop();
  263.  
  264. //all the adjacent vertices
  265. edge = g[vertex].next;
  266. while(edge)
  267. {
  268. if(g[edge->vertex].color == WHITE){
  269. g[edge->vertex].color = GRAY;
  270. cout << g[edge->vertex].element << " ";
  271. //enqueue
  272. q.push(edge->vertex);
  273. }
  274. edge = edge->next;
  275. }
  276. g[vertex].color = BLACK;
  277. }//end of while
  278.  
  279. cout << endl;
  280. }
  281.  
  282. int main()
  283. {
  284. Graph graph;
  285. int num_vertices = 8;
  286.  
  287. graph = Create(graph, num_vertices);
  288.  
  289. InsertEdge(graph,0,1);
  290. InsertEdge(graph,1,2);
  291. InsertEdge(graph,2,3);
  292. InsertEdge(graph,3,2);
  293. InsertEdge(graph,4,0);
  294. InsertEdge(graph,1,5);
  295. InsertEdge(graph,2,6);
  296. InsertEdge(graph,3,7);
  297. InsertEdge(graph,1,4);
  298. InsertEdge(graph,4,5);
  299. InsertEdge(graph,5,6);
  300. InsertEdge(graph,6,7);
  301. InsertEdge(graph,7,7);
  302. InsertEdge(graph,6,5);
  303.  
  304. OutPut(graph, num_vertices);
  305. DFS(graph, num_vertices);
  306. BFS(graph, num_vertices, 0);
  307.  
  308. graph = DeleteGraph(graph, num_vertices);
  309.  
  310. return 0;
  311. }

数据结构 《2》----基于邻接表表示的图的实现 DFS(递归和非递归), BFS的更多相关文章

  1. 图的基本操作(基于邻接表):图的构造,深搜(DFS),广搜(BFS)

    #include <iostream> #include <string> #include <queue> using namespace std; //表结点 ...

  2. SDUT 2142 数据结构实验之图论二:基于邻接表的广度优先搜索遍历

    数据结构实验之图论二:基于邻接表的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Descript ...

  3. 数据结构C++使用邻接表实现图

    定义邻接表存储的图类.[实验要求] (1)创建一个邻接表存储的图:(2)返回图中指定边的权值:(3)插入操作:向图中插入一个顶点,插入一条边:(4)删除操作:从图中删除一个顶点,删除一条边:(5)图的 ...

  4. 无向图的 DFS 和 BFS实现 (以邻接表存储的图)

    #include <iostream> #include <queue> using namespace std; #define MaxVertexNum 10 typede ...

  5. 数据结构二叉树的递归与非递归遍历之java,javascript,php实现可编译(1)java

    前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序 ...

  6. 数据结构作业——图的存储及遍历(邻接矩阵、邻接表+DFS递归、非递归+BFS)

    邻接矩阵存图 /* * @Author: WZY * @School: HPU * @Date: 2018-11-02 18:35:27 * @Last Modified by: WZY * @Las ...

  7. SDUT2142数据结构实验之图论二:基于邻接表的广度优先搜索遍历

    http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2142&cid=1186 题目描述 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜 ...

  8. Invitation Cards(邻接表+逆向建图+SPFA)

    Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 17538   Accepted: 5721 Description In ...

  9. 基于邻接表的长度为k的简单路径的求解

    描述 一个连通图采用邻接表作为存储结构.设计一个算法,判断无向图中任意给定的两点是否存在一条长度为k的简单路径. 输入 多组数据,每组m+3数据行.第一行有两个数字n,m和k,代表有n个顶点,m条边和 ...

随机推荐

  1. WAMP 403 Forbidden禁止访问 的解决办法

    修改httpd.conf文件 # onlineoffline tag - don't remove Require local To # onlineoffline tag - don't remov ...

  2. valuestack,stackContext,ActionContext.之间的关系

    者之间的关系如下图所示: relation ActionContext 一次Action调用都会创建一个ActionContext 调用:ActionContext context = ActionC ...

  3. javaWeb学习之运用myeclipse结合tomcat开发一些简单的jsp和service

    servlet是什么?     servlet是java服务器端编程.不同于我们之前写的一般的java应用程序,Servlet程序是运行在服务器上的,服务器有很多种.....现在只是用过 tomcat ...

  4. SQL Server数据库(SQL Sever语言 事务)

    事务:保障流程的完整执行保证程序某些程序在运行时同时成功同时失败,保证程序的安全性 begin tran --在流程开始的位置加 --此处写SQL语句 if @@error>0 --ERRORS ...

  5. class、interface、struct的区别

    1 struct和class有什么区别 1.1默认的继承访问权限 Struct是public的,class是private的. 你可以写如下的代码: struct A { char a; }; str ...

  6. css——子代与后代选择器

    一直都以为,子代选择器与后代选择器作用是一样的,都是选择一个元素下面的子元素,直到今天才明白: 1.子代选择器(用<连接):ul>li 子选择器仅仅选择ul包围的 子元素 中的 li元素, ...

  7. 发送广播BroadcastReceiver

    import android.os.Bundle;import android.app.Activity;import android.content.Intent;import android.vi ...

  8. [css]邮件的写法

    <style type="text/css">        /* Client-specific Styles */        #outlook a{paddin ...

  9. ASP.NET MVC学习之路由篇(3)

    根据路由输出链接 既然是网站开发自然少不了链接,我们已经学会了强大的路由,但是还缺少一步就是能够将这些路由的路径输出到页面,下面我们就开始学习如何输出路由路径. 首先我们的路由注册部分如下所示: 1 ...

  10. [转载]查看基于Android 系统单个进程内存、CPU使用情况的几种方法

    转载自: http://www.linuxidc.com/Linux/2011-11/47587.htm 一.利用Android API函数查看1.1 ActivityManager查看可用内存. A ...