数据结构 《2》----基于邻接表表示的图的实现 DFS(递归和非递归), BFS
2014-01-13 15:32
671 查看
图通常有两种表示方法: 邻接矩阵 和 邻接表
对于稀疏的图,邻接表表示能够极大地节省空间。
以下是图的数据结构的主要部分:
struct Vertex{
ElementType element; //节点的名字
Edge *next; //所包含的边组成的单链表的头指针
};
struct Edge{
int adj; //节点的标号(0-number of nodes)
Edge *next;
};
注意,实际应用中,节点都有名字,而不是数字,所以我们需要提供从名字到标号的映射。
最简单的方法就是 Hash(散列表),或者二叉查找树之类的能够快速提供查询的数据结构。
本文的处理较为简单: 节点的名字是 'a' ---- 'z', 所以映射通过简单的运算即可实现: node id = node name - 'a'.
![](http://img.blog.csdn.net/20140113152023421?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hvdWxpbmp1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
对于稀疏的图,邻接表表示能够极大地节省空间。
以下是图的数据结构的主要部分:
struct Vertex{
ElementType element; //节点的名字
Edge *next; //所包含的边组成的单链表的头指针
};
struct Edge{
int adj; //节点的标号(0-number of nodes)
Edge *next;
};
注意,实际应用中,节点都有名字,而不是数字,所以我们需要提供从名字到标号的映射。
最简单的方法就是 Hash(散列表),或者二叉查找树之类的能够快速提供查询的数据结构。
本文的处理较为简单: 节点的名字是 'a' ---- 'z', 所以映射通过简单的运算即可实现: node id = node name - 'a'.
// copyright @ L.J.SHOU Jan.13, 2014 #include "graph.h" #include <ctime> #include <iostream> #include <stack> #include <queue> using namespace std; typedef char ElementType; typedef Vertex* Graph; enum Color{WHITE, GRAY, BLACK}; struct Edge { int vertex; int weight; Edge *next; }; struct Vertex { Color color; ElementType element; int start, finish; Edge *next;//head of adjacent list }; Graph Create(Graph graph, int n) { graph = new Vertex ; for(int i=0; i<n; ++i) { graph[i].color = WHITE; graph[i].element = i + 'a'; graph[i].start = 0; graph[i].finish = 0; graph[i].next = NULL; } return graph; } // Reset Graph void Clear(Graph graph, int n) { for(int i=0; i<n; ++i) { graph[i].color = WHITE; graph[i].start = 0; graph[i].finish = 0; } } Graph DeleteGraph(Graph graph, int n) { for(int i=0; i<n; ++i) { Edge* head(graph[i].next), *next(NULL); while(head) { next = head->next; delete head; head = next; } } delete [] graph; return NULL; } // return the outdegree of vertex i int OutDegree(Graph g, int i) { int num(0); Edge* link(g[i].next); while(link) { link = link->next; ++ num; } return num; } // test whether edge(i, j) exists bool Exist(Graph g, int i, int j) { Edge *link(g[i].next); while(link && link->vertex != j) link = link->next; if(link == NULL) return false; else return true; } bool InsertEdge(Graph g, int i, int j) { if(Exist(g, i, j)){ cout << "edge (" << i << "," << j << ") already existed" << endl; return false; } Edge *edge(NULL); edge = new struct Edge; edge->vertex = j; edge->next = g[i].next; g[i].next = edge; return true; } bool DeleteEdge(Graph g, int i, int j) { if(!Exist(g, i, j)){ cout << "edge (" << i << "," << j << ") doesn't exist" << endl; return false; } Edge *cur(g[i].next), *pre(cur); while(cur && cur->vertex != j) { pre = cur; cur = cur->next; } if(pre == NULL) { // delete head edge g[i].next = cur->next; delete cur; } else { pre->next = cur->next; delete cur; } return true; } // print adjacent list void OutPut(Graph g, int n) { Edge *edge(NULL); for(int i=0; i<n; ++i) { cout << g[i].element << "->"; edge = g[i].next; while(edge) { cout << g[edge->vertex].element << "->"; edge = edge->next; } cout << "NULL" << endl; } } void DFS(Graph graph, int n) { cout << "DFS: " << endl;; Clear(graph, n); for(int i=0; i<n; ++i) { if(graph[i].color == WHITE) DFSVisit(graph, i); } cout << endl; cout << "DFS_stack: " << endl; Clear(graph, n); for(int i=0; i<n; ++i) { if(graph[i].color == WHITE) DFSVisitStack(graph, i); } cout << endl; } // recursive DFS void DFSVisit(Graph graph, int i) { static int time(0); Edge *link(graph[i].next); cout << graph[i].element << " "; graph[i].color = GRAY; graph[i].start = ++time; while(link) { if(graph[link->vertex].color == WHITE) DFSVisit(graph, link->vertex); link = link->next; } graph[i].finish = ++time; graph[i].color = BLACK; } // non-recursive DFS void DFSVisitStack(Graph g, int i) { static int time(0); struct Edge* edge; int vertex; stack<int> s; //visit vertex i cout << g[i].element << " "; g[i].color = GRAY; g[i].start = ++time; s.push(i); while(!s.empty()) { vertex = s.top(); edge = g[vertex].next; while(edge) { if(g[edge->vertex].color == WHITE) { s.push(edge->vertex); cout << g[edge->vertex].element << " "; g[edge->vertex].start = ++time; g[edge->vertex].color = GRAY; break; } edge = edge->next; } //vertex's neigbours have been visited if(edge == NULL){ s.pop(); g[vertex].color = BLACK; g[vertex].finish = ++time; } } } ///////////////////////////////////////////////////////////// // search all vertices that can be rearched from Source s /// // compute the distances from source s /// /////////////// ///////////////////////////////////////////////////////////// void BFS(Graph g, int n, int s) { queue<int> q; Edge *edge(NULL); int vertex; //visit source vertex Clear(g, n); cout << "BFS: " << endl;; cout << g[s].element << " "; g[s].color = GRAY; q.push(s); while(!q.empty()) { //dequeue vertex = q.front(); q.pop(); //all the adjacent vertices edge = g[vertex].next; while(edge) { if(g[edge->vertex].color == WHITE){ g[edge->vertex].color = GRAY; cout << g[edge->vertex].element << " "; //enqueue q.push(edge->vertex); } edge = edge->next; } g[vertex].color = BLACK; }//end of while cout << endl; } int main() { Graph graph; int num_vertices = 8; graph = Create(graph, num_vertices); InsertEdge(graph,0,1); InsertEdge(graph,1,2); InsertEdge(graph,2,3); InsertEdge(graph,3,2); InsertEdge(graph,4,0); InsertEdge(graph,1,5); InsertEdge(graph,2,6); InsertEdge(graph,3,7); InsertEdge(graph,1,4); InsertEdge(graph,4,5); InsertEdge(graph,5,6); InsertEdge(graph,6,7); InsertEdge(graph,7,7); InsertEdge(graph,6,5); OutPut(graph, num_vertices); DFS(graph, num_vertices); BFS(graph, num_vertices, 0); graph = DeleteGraph(graph, num_vertices); return 0; }
相关文章推荐
- 数据结构之双线链表
- 数据结构之单链表操作
- d3.js学习笔记(五)——将数据结构化为D3.js可处理的
- 数据结构⑤-树I
- OpenCV中数据结构的操作方法
- 【数据结构】线性循环队列
- 数据结构之线性表(一)
- 数据结构《1》---单链表
- 数据结构《1》---单链表
- zoj3284Matrix Processing(二维树状数组)
- hdu3308 LCIS(线段树区间合并)
- zoj2301Color the Ball(线段树,离散化,成段更新)
- 《Thinking In Algorithm》03.数据结构之数组
- (数据结构)栈_迷宫求解(严蔚敏P50) _模仿
- 随便写了个堆排序程序
- 顺序表内查找元素
- C++ 数据结构和算法
- 数据结构之链表学习(1)
- 数据结构之图
- Wikipedia中「Trie」条目的翻译(部分)