详解数据结构——图之邻接矩阵表示法
2016-10-29 22:54
309 查看
一、图的建立
图是表达“多对多”的关系的一种数据结构。
它由非空的有限顶点集合和有限边集合组成。
1. 顶点集合常常由数组表示。
数组下标表示顶点位置。
数组内容包含顶点数据,并且要添加判定是否被访问过的标志标量,为其余操作提供参数。
其数据类型定义如下:
struct Vertex {
T data;
bool isVisited;
}
2. 边集合的存储常用邻接矩阵或者邻接表。
边数值(权值)表示顶点之间有某种关系,0表示两个顶点之间没有边,也即没有关系。
邻接矩阵是一个二维数组,matrix[顶点数][顶点数]。也可定义为一个省一半空间的一维数组 n(n+1)/2,不利于理解,不作说明。
最简单的图用来呈现顶点之间的关系。顶点类型可以只包含一个用来判断是否被访问过的标志变量。用bool或者int数组表示顶点。
<pre name="code" class="cpp">//graph.h#ifndef GRAGH_H
#define GRAGH_H
class Graph {
public:
Graph(const int &capacity);
~Graph();
void insertEdge(const int &indexA, const int &indexB, const int &weight = 1);
//成员变量只需要三个。
private:
int capacity; //图的顶点个数。
bool *pVertex; //存储图的顶点。
int *pMatrix; //存储图的边。
}
#endif
实现文件:
//graph.cpp
#include "graph.h"
/*
通过初始化列表建立一张图。
并对pVertex、pMatrix进行值初始化。
pVertex的每个元素值初始化为false,pMatrix的每个元素值初始化为0.
*/
inline
Graph::Graph(const int &capacity):
capacity(capacity),
pVertex(new bool[capacity]()),
pMatrix(new int[capacity * capacity]()) {}
<span style="color:#808000;">inline</span><pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="color:#800080;">Graph</span><span style="color:#000000;">::~</span><span style="color:#800080;">Graph</span><span style="color:#000000;">()</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">{</span>
inline
void Graph::insertEdge(const
int
&indexA,
const
int &indexB,
const
int weight)
{
1. pVertex下标表示顶点位置。
2. pVertex值表示顶点是否被访问过,初始化为false。
3. pMatrix值表示顶点之间的关系,初始化为0。
4. 添加边的信息,就形成了一张图。
二、图的遍历
有了图之后,我们就要对它进行一些操作。
首先是遍历:
1. 深度优先搜索Depth First Search,类似于树的先序遍历。
2. 广度优先搜索Breadth First Search,类似于树的层序遍历。
为此,在graph.h头文件中添加四个函数:
//graph.h
public:
<span style="color:#808000;"> void</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">DFS</span><span style="color:#000000;">(</span><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">&</span>index<span style="color:#000000;">);</span><pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="color:#c0c0c0;"> </span><span style="color:#808000;">void</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">BFS</span><span style="color:#000000;"
4000
>(</span><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">&</span>index<span style="color:#000000;">);</span>
其中的resetVertex是用来在下一个遍历之前,重置所有的顶点为未访问过的状态。
若是用int数组表示,则可传入一个值,用来判定顶点的访问状态,也就不需要resetVertex。
而getEdgeWeight函数是返回从A点到B点的边的权值,代表了两个顶点的关系。
其实现如下:
//graph.cpp
#include <iostream>
#include <queue> //包含头文件,为BFS提供队列容器。
<span style="color:#808000;">inline</span><pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#000000;">&</span><span style="color:#c0c0c0;"> </span><span style="color:#800080;">Graph</span><span style="color:#000000;">::</span><span style="color:#000000;">getEdgeWeight</span><span style="color:#000000;">(</span><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">&</span><span style="color:#000000;">indexA</span><span style="color:#000000;">,</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">&</span><span style="color:#000000;">indexB</span><span style="color:#000000;">)</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">{</span>
//打印出从index开始,进行深度优先的索引次序。
//重置顶点为未访问过。
三、最短路径Shortest Path
图的重要应用之一,最短路径。
。。。怎么感觉写博客好累啊,写了一个多小时,才写了这么点儿。
后面的最短路径和最小生成树感觉这样写下去得四五个小时。
有空再写完。
图是表达“多对多”的关系的一种数据结构。
它由非空的有限顶点集合和有限边集合组成。
1. 顶点集合常常由数组表示。
数组下标表示顶点位置。
数组内容包含顶点数据,并且要添加判定是否被访问过的标志标量,为其余操作提供参数。
其数据类型定义如下:
struct Vertex {
T data;
bool isVisited;
}
2. 边集合的存储常用邻接矩阵或者邻接表。
边数值(权值)表示顶点之间有某种关系,0表示两个顶点之间没有边,也即没有关系。
邻接矩阵是一个二维数组,matrix[顶点数][顶点数]。也可定义为一个省一半空间的一维数组 n(n+1)/2,不利于理解,不作说明。
最简单的图用来呈现顶点之间的关系。顶点类型可以只包含一个用来判断是否被访问过的标志变量。用bool或者int数组表示顶点。
<pre name="code" class="cpp">//graph.h#ifndef GRAGH_H
#define GRAGH_H
class Graph {
public:
Graph(const int &capacity);
~Graph();
void insertEdge(const int &indexA, const int &indexB, const int &weight = 1);
//成员变量只需要三个。
private:
int capacity; //图的顶点个数。
bool *pVertex; //存储图的顶点。
int *pMatrix; //存储图的边。
}
#endif
实现文件:
//graph.cpp
#include "graph.h"
/*
通过初始化列表建立一张图。
并对pVertex、pMatrix进行值初始化。
pVertex的每个元素值初始化为false,pMatrix的每个元素值初始化为0.
*/
inline
Graph::Graph(const int &capacity):
capacity(capacity),
pVertex(new bool[capacity]()),
pMatrix(new int[capacity * capacity]()) {}
<span style="color:#808000;">inline</span><pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="color:#800080;">Graph</span><span style="color:#000000;">::~</span><span style="color:#800080;">Graph</span><span style="color:#000000;">()</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">{</span>
delete[] pVertex;
delete[] pMatrix;
}
inline
void Graph::insertEdge(const
int
&indexA,
const
int &indexB,
const
int weight)
{
//插入一条从A点指向B点的边。
pMatrix[indexA * capacity + indexB] = weight;
//无向图需要插入一条从B指向A的边。
pMatrix[indexB * capacity + indexA] = weight;
}
1. pVertex下标表示顶点位置。
2. pVertex值表示顶点是否被访问过,初始化为false。
3. pMatrix值表示顶点之间的关系,初始化为0。
4. 添加边的信息,就形成了一张图。
二、图的遍历
有了图之后,我们就要对它进行一些操作。
首先是遍历:
1. 深度优先搜索Depth First Search,类似于树的先序遍历。
2. 广度优先搜索Breadth First Search,类似于树的层序遍历。
为此,在graph.h头文件中添加四个函数:
//graph.h
public:
<span style="color:#808000;"> void</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">DFS</span><span style="color:#000000;">(</span><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">&</span>index<span style="color:#000000;">);</span><pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="color:#c0c0c0;"> </span><span style="color:#808000;">void</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">BFS</span><span style="color:#000000;"
4000
>(</span><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">&</span>index<span style="color:#000000;">);</span>
void resetVertex(); private:
const int& getEdgeWeight(const int &indexA, const int &indexB);
其中的resetVertex是用来在下一个遍历之前,重置所有的顶点为未访问过的状态。
若是用int数组表示,则可传入一个值,用来判定顶点的访问状态,也就不需要resetVertex。
而getEdgeWeight函数是返回从A点到B点的边的权值,代表了两个顶点的关系。
其实现如下:
//graph.cpp
#include <iostream>
#include <queue> //包含头文件,为BFS提供队列容器。
<span style="color:#808000;">inline</span><pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#000000;">&</span><span style="color:#c0c0c0;"> </span><span style="color:#800080;">Graph</span><span style="color:#000000;">::</span><span style="color:#000000;">getEdgeWeight</span><span style="color:#000000;">(</span><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">&</span><span style="color:#000000;">indexA</span><span style="color:#000000;">,</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">const</span><span style="color:#c0c0c0;"> </span><span style="color:#808000;">int</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">&</span><span style="color:#000000;">indexB</span><span style="color:#000000;">)</span><span style="color:#c0c0c0;"> </span><span style="color:#000000;">{</span>
return pMatrix[indexA * capacity + indexB];
}
//打印出从index开始,进行深度优先的索引次序。
void Graph::DFS(const int &index) {
std::cout << index << " ";
pVertex[index] = true;
for(int i(0); i < capacity; ++i) {
if(getEdgeWeight(index, i) > 0 && !pVertex[i])
DFS(i);
}
} /打印出从index开始,进行广度优先的索引次序。
void Graph::BFS(const int &index) {
std::queue<int> que;
que.push(index);
pVertex[index] = true;
while(!que.empty()) {
int subcript(que.front());
que.pop();
std::cout << subcript << " ";
for(int i(0); i < capacity; ++i) {
if(getEdgeWeight(subcript, i) > 0 && !pVertex[i]) {
que.push(i);
pVertex[i] = true;
}
}
}
}
//重置顶点为未访问过。
void Graph::resetVertex() {
for(int i(0); i < capacity; ++i)
pVertex[i]= false;
}
三、最短路径Shortest Path
图的重要应用之一,最短路径。
。。。怎么感觉写博客好累啊,写了一个多小时,才写了这么点儿。
后面的最短路径和最小生成树感觉这样写下去得四五个小时。
有空再写完。
相关文章推荐
- 7-1-图、表的数组(邻接矩阵)表示法-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
- JavaScript数据结构之广义表的定义与表示方法详解
- 数据结构 学习笔记(七):图(上):图的表示方法(邻接表,邻接矩阵),遍历(DFS,BFS)
- 【数据结构】邻接矩阵表示法的图的深度广度优先遍历递归和非递归遍历
- C++面向对象的数据结构之 图(邻接矩阵表示)
- 数据结构C语言--邻接矩阵表示有向网
- 数据结构中用图的邻接矩阵的表示以及深度搜索
- 【数据结构】邻接矩阵表示法的图的深度广度优先遍历递归和非递归遍历
- 《数据结构》示范程序/图邻接矩阵表示
- 数据结构 图的邻接表表示转换成邻接矩阵表示的算法
- 数据结构的C实现_图_邻接矩阵表示
- 【c/c++ 算法/数据结构】 邻接矩阵表示图,深度,广度优先遍历 算法设计+代码+图片
- 数据结构——邻接矩阵表示的图的Floyd算法
- 树的孩子表示法,树的兄弟表示法,树的存储结构详解,数据结构-树的学习(2)
- 图的邻接矩阵表示广度深度遍历大连理工大学数据结构上机
- 数据结构——邻接矩阵表示的图的Dijkstra算法
- 数据结构-图的邻接矩阵表示
- 数据结构,图的邻接矩阵表示
- 数据结构 图的邻接矩阵表示法
- 数据结构之图(C++)--邻接矩阵表示(一)