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

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

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

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[n];
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;
}

数据结构 《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. 《Java程序设计》实验四 实验报告

    实验四 Android开发基础 实验内容 XP基础 XP核心实践 相关工具 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器> 课程 ...

  2. ARM字节对齐问题详解

    一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这 ...

  3. 张艾迪Eidyzhang:解码天才Eidyzhang的诞生

    AOA解码:天才Eidyzhang的诞生AOA深度解读:世界第一天才Eidyzhang: (TheWorldNo.1Girl+TheWorldNo.1InterentGirl+世界第一女孩+世界第一互 ...

  4. IKAnalyzer进行中文分词和去停用词

    最近学习主题模型pLSA.LDA,就想拿来试试中文.首先就是找文本进行切词.去停用词等预处理,这里我找了开源工具IKAnalyzer2012,下载地址:(:(注意:这里尽量下载最新版本,我这里用的IK ...

  5. mustache模板技术

    一.简介Web 模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,通常是标准的 HTML 文档.当然不同的开发语言有不同模板引擎,如 Javascript 下的 Hog ...

  6. RRDTool 存储原理简介——基于时间序列的环型数据库

    转自:http://www.jianshu.com/p/b925b1584ab2 RRDTool是一套监测工具,可用于存储和展示被监测对象随时间的变化情况.比如,我们在 Windows 电脑上常见的内 ...

  7. 9个充满想象力的 JavaScript 物理和重力实验

    在这个列表中挑选了9个物理和重力实验,用来展示 Javascript 的强大.几年前,所有这些实验都必须使用 Java 或 Flash 才能做.在下面这些惊人的例子中,就个人而言,我比较喜欢仿真布料的 ...

  8. xml数据解析调研

    XML数据解析http://www.tuicool.com/articles/Nraau2(必用) http://www.cnblogs.com/pengyingh/articles/2342699. ...

  9. POJ 1573 Robot Motion 模拟 难度:0

    #define ONLINE_JUDGE #include<cstdio> #include <cstring> #include <algorithm> usin ...

  10. ARM2440换lcd

    将原来的3.5寸分辨率为240x320换为480x272所需要修改的地方 时序设置: CLKVAL=4    (VCLK   =10)    5<  VCLK   <12 每个点扫描周期 ...