数据结构学习(C++)之图

图的应用恐怕是所有数据结构中最宽泛的了,但这也注定了在讲“数据结构的图”的时候没什么好讲的——关于图的最重要的是算法,而且相当的一部分都是很专业的,一般的人几乎不会接触到;相对而言,结构就显得分量很轻。你可以看到关于图中元素的操作很少,远没有单链表那里列出的一大堆“接口”。——一个结构如果复杂,那么能确切定义的操作就很有限。

基本储存方法

不管怎么说,还是先得把图存起来。不要看书上列出了好多方法,根本只有一个——邻接矩阵。如果矩阵是稀疏的,那就可以用十字链表来储存矩阵(见前面的《稀疏矩阵(十字链表)》)。如果我们只关系行的关系,那么就是邻接表(出边表);反之,只关心列的关系,就是逆邻接表(入边表)。

下面给出两种储存方法的实现。

#ifndef Graphmem_H
#define Graphmem_H
#include <vector>
#include <list>
using namespace std;
template <class name, class dist, class mem> class Network;
const int maxV = 20;//最大节点数
template <class name, class dist>
class AdjMatrix
{
friend class Network<name, dist, AdjMatrix<name, dist> >;
public:
AdjMatrix() : vNum(0), eNum(0)
{
vertex = new name[maxV]; edge = new dist*[maxV];
for (int i = 0; i < maxV; i++) edge[i] = new dist[maxV];
}
~AdjMatrix()
{
for (int i = 0; i < maxV; i++) delete []edge[i];
delete []edge; delete []vertex;
}
bool insertV(name v)
{
if (find(v)) return false;
vertex[vNum] = v;
for (int i = 0; i < maxV; i++) edge[vNum][i] = NoEdge;
vNum++; return true;
}
bool insertE(name v1, name v2, dist cost)
{
int i, j;
if (v1 == v2 || !find(v1, i) || !find(v2, j)) return false;
if (edge[i][j] != NoEdge) return false;
edge[i][j] = cost; eNum++; return true;
}
name& getV(int n) { return vertex[n]; } //没有越界检查
int nextV(int m, int n)//返回m号顶点的第n号顶点后第一个邻接顶点号,无返回-1
{
for (int i = n + 1; i < vNum; i++) if (edge[m][i] != NoEdge) return i;
return -1;
}
private:
int vNum, eNum;
dist NoEdge, **edge; name *vertex;
bool find(const name& v)
{
for (int i = 0; i < vNum; i++) if (v == vertex[i]) return true;
return false;
}
bool find(const name& v, int& i)
{
for (i = 0; i < vNum; i++) if (v == vertex[i]) return true;
return false;
}
};
template <class name, class dist>
class LinkedList
{
friend class Network<name, dist, LinkedList<name, dist> >;
public:
LinkedList() : vNum(0), eNum(0) {}
~LinkedList()
{
for (int i = 0; i < vNum; i++) delete vertices[i].e;
}
bool insertV(name v)
{
if (find(v)) return false;
vertices.push_back(vertex(v, new list<edge>));
vNum++; return true;
}
bool insertE(const name& v1, const name& v2, const dist& cost)
{
int i, j;
if (v1 == v2 || !find(v1, i) || !find(v2, j)) return false;
for (list<edge>::iterator iter = vertices[i].e->begin();
iter != vertices[i].e->end() && iter->vID < j; iter++);
if (iter == vertices[i].e->end())
{
vertices[i].e->push_back(edge(j, cost)); eNum++; return true;
}
if (iter->vID == j) return false;
vertices[i].e->insert(iter, edge(j, cost)); eNum++; return true;
}
name& getV(int n) { return vertices[n].v; } //没有越界检查
int nextV(int m, int n)//返回m号顶点的第n号顶点后第一个邻接顶点号,无返回-1
{
for (list<edge>::iterator iter = vertices[m].e->begin();
iter != vertices[m].e->end(); iter++) if (iter->vID > n) return iter->vID;
return -1;
}
private:
bool find(const name& v)
{
for (int i = 0; i < vNum; i++) if (v == vertices[i].v) return true;
return false;
}
bool find(const name& v, int& i)
{
for (i = 0; i < vNum; i++) if (v == vertices[i].v) return true;
return false;
}
struct edge
{
edge() {}
edge(int vID, dist cost) : vID(vID), cost(cost) {}
int vID;
dist cost;
};
struct vertex
{
vertex() {}
vertex(name v, list<edge>* e) : v(v), e(e) {}
name v;
list<edge>* e;
};
int vNum, eNum;
vector<vertex> vertices;
};
#endif

这个实现是很简陋的,但应该能满足后面的讲解了。现在这个还什么都不能做,不要急,在下篇将讲述图的DFS和BFS。

时间: 2024-08-29 06:35:52

数据结构学习(C++)之图的相关文章

JavaScript数据结构和算法之图和图算法

 这篇文章主要介绍了JavaScript数据结构和算法之图和图算法,本文讲解了有向图.无序图.简单图.图的遍历等内容,需要的朋友可以参考下     图的定义 图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合. 有向图 有向边:若从顶点Vi到Vj的边有方向,则称这条边为有向边,也成为弧(Arc),用有序偶<Vi,Vj>来表示,Vi称为弧尾,Vj称为弧头. 无序图 无向边:若顶点Vi到Vj之间的边没

Windows phone 8 学习笔记(5) 图块与通知

原文:Windows phone 8 学习笔记(5) 图块与通知 基于metro风格的Windows phone 8 应用提到了图块的概念,它就是指启动菜单中的快速启动图标.一般一个应用必须有一个默认图块,还可以有若干个次要图块.另外,通知与图块的关系比较密切,我们可以通过在接受到消息时动态更新图块来达到适时的效果.我们本节把图块和通知放在一起讲. 快速导航:    一.图块    二.图块更新计划    三.本地通知    四.推送通知 一.图块 1)定义默认图块 默认图块只能在清单文件中定义

数据结构学习(C++)之双向链表

原书这部分内容很多,至少相对于循环链表是很多.相信当你把单链表的指针域搞清楚后,这部分应该难不倒你.现在我的问题是,能不能从单链表派生出双向链表?<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />你可以有几种做法: 一种就是先定义一个双链节点--但是,它的名字必须叫Node,这是没办法的事:不然你就只好拷贝一份单链表的实现文件,把其中的Node全都替换成你的双链节点名字,但

数据结构学习笔记

在网上有较多的数据结构视频课,我通过学习邓俊辉的网课免费视频来学习的.他的视频讲得还很详细,比较适合刚入门的与那些即将毕业,找工作但是数据结构比较薄弱的同学来学习. 向量 有很多接口方法. 可扩充向量:总容量capacity,size当前的实际规模.当size不及capacity一半是,会下溢(装填因子=size/capacity). 动态空间管理:当即将上溢时,就会适当的扩容.

数据结构学习笔记--队列

引子:只有学习才是激情的生命,才是燃烧的岁月,才是完美的人生 声明:本笔记由<嵌入式系统软件设计中的数据结构>产生,旨在提升自己的软件设计水平,绝无侵权行为,望转载者备注说明 一 队列逻辑结构 1 是一种只允许在表的一端-"队尾"进行插入,而在另一端-"队头"进行删除的线性表.实则为线性表的一种特例.也称为先进先出表 2 当队列中没有结点时称为空队列.队列的修改是依照先进先出的原则进行的 二 队列的基本运算 置空队 SetNull(Q):将队列 Q 置成

答读者问(24):一个大二学生有关数据结构学习的疑问及答复

       最近,在V众投上有一个标题为"最近学习数据结构陷入了死循环大脑一片空白"的问题(http://www.vzhongtou.com/question/744),具体内容如下:         大一下学期学历c语言 学了半吊子 大二一开学就开始讲数据结构 没学过汇编啥的 我知道c语言的指针很重要就复习了指针现在对指针有所了解 老师讲课是一星期讲两节大课 一大章一节讲课一节上机 只讲伪算法 现在讲到树了感觉太抽象了完全搞不懂 本人数学基础比较薄弱 另外感觉自己的逻辑和抽象思维有

Python高级数据结构学习教程

本文虽然不是很深入,不过实例比较多,学习Python高级数据结构的好基础教程. 数据结构的概念 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据结构,分别是List.Tuple.Dictionary以及Set.大部分的应用程序不需要其他类型的数据结构,但若是真需要也有很多高级数据结构可供选择,例如Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint.本文将介绍

通过改写算法获得数据结构学习的更佳效果

[事件] 某名数据结构基础网络学员在"单链表的基本算法"部分连问两个问题: 老师,我while语句里面j<i-1改为j<i,else里面直接q=p可以么? 老师,你这样万一刚好q->next==NULL呢,这样没影响吧? 我的"即时"回答,也已经是10个小时之后了,我不知道他看到解答后,状态还在不在.另外,这种问题,并非是可以.不行就简单回答的,背后很细致的考量,用有限的文字根本说不清楚. 这名认真学习.主动思考的学员,此时需要的是在学习方法上的改

一脸懵逼学习oracle(图形化界面操作---》PLSQL图形化界面)

1:经过几天的折腾,终于将oracle安装成功,创建用户,授权等等操作,接下来就安安心心学习oracle: 安装好PLSQL图形化界面和汉化以后(过程自己百度吧,百度more and more),登录图形化界面的时候就是这个B样:   2:登录成功以后就是这个B样: 左侧有三栏,自己根据需要自己拉查看信息就可以了,比如这样: 3:新建一个数据表: 点击新建然后就是这个样子的:起好数据表名称   新建数据表的列是这样子的: 4:插入数据是这样子的: 插入数据是这个样子的,点对号保存数据,点提交进行