您的位置:首页 > 理论基础 > 数据结构算法

数据结构C++语言实现——图

2015-12-14 21:23 585 查看

图的基本概念

图是数据结构G=(V,E)

V(G)是G中结点的有限非空集合

E(G)是G中边的有限集合

若图中代表一条边的偶对是有序的,则称为有向图,<
u,v
>u称为该边的始点(尾)

,v称为边的终点(头)。有向边也称为弧。

如果边(u,u)或者<
u,u
>被允许称为自回路。

如果两顶点间允许有多条相同边的图,称为多重图。

如果一个图有最多的边称为完全图。

子图:G=(V’,E’)其中V’(G)是V(G),E’(G)是E(G)子集。

路径:是一个顶点序列,其中一个回路是一条简单路径。

一个无向图中,若两个顶点之间存在一条路径,则称两个顶点之间连通。如果所有两个顶点都是连通的,此图称为连通图

一个有向图中,任意一对顶点,存在一个顶点到另一个顶点的路径,并且同时存在另一个顶点到这个顶点的路径,则称此图是强连通图。

无向连通图的生成树是一个极小连通子图,它包括图中全部顶点,但只有足以构成一棵树的n-1条边。

图ADT

//ADT Graph{
数据:
顶点的非空集合V和边的集合E,每条边由V中顶点的偶对<u,v>表示
运算:
Create():构造一个不包含任何边的有向图
Destroy():撤销一个有向图
Exist(u,v):如果图中存在边<u,v>,则函数返回true,否则返回false
Insert(u,v,w):向图中添加权为w的边<u,v>,若插入成功,则函数返回Success;若图中已存在边<u,v>,则函数返回Duplicate;其他情况函数返回Failure
Remove(u,v):从图中删除边<u,v>,若图中不存在边<u,v>,则返回NotPresent;若图中已存在边<u,v>,则从图中删除此边,函数返回Success;其他情况函数返回Failure.
Vertices():函数返回图中顶点数目

//Graph 类
template<class T>
class Graph
{
public:
Virtual ResultCode Insert(int u,int v,T& w)=0;
Virtual ResultCode Remove(int u,int v)=0;
Virtual bool Exist(int u,int v)const=0;
Virtual int Vertices()const{return n;}

protected:
int n,e;
};


图的储存结构

图的矩阵表示法

邻接矩阵

是表示图中顶点之间相邻关系的矩阵,一个有n个顶点的图G=(V,E)的邻接矩阵是一个n*n的矩阵A。

如果G是无向图,那么A中元素定义

A[u][v]=1 如果(u,v)属于集合E(G)

A[u][v]=0 其他

如果G是有向图,那么A中元素定义如下

A[u][v]=1 如果<
u,v
>属于集合E(G)

A[u][v]=0 其他

关联矩阵

有向图G(V,E)的关联矩阵定义如下n*m阶矩阵

A[v][j]=1 顶点v是弧j的起点

A[v][j]=-1 顶点v是弧j的终点

A[v][j]=0 顶点v与弧j不相关联

邻接矩阵的实现

邻接矩阵有两种,不带权图和网的邻接矩阵。可以用一个三元组(u,v,w)代表一条边,u和v是边的两个顶点,w表示顶点u和v的下列关系。

1。a[u][u]=0:两种邻接矩阵的主对角线元素都是0;

2。a[u][v]=w:若边<
u,v
>属于集合E,则w=1(不带权图)或w=w(i,j)(网);若边<
u,v
>不属于E则w=noEdge,noEdge=0(不带权图)或noEdge=无穷(网)

邻接矩阵类

//MGraph类
template<class T>
class MGraph:public Graph<T>
{
public:
MGraph(int mSize,const T& noedg);
~MGraph();
ResultCode Insert(int u,int v,T& w);
ResultCode Remove(int u,int v);
bool Exist(int u,int v)const;
.
.
.
protected:
T**a;
T noEdge;
};


构造函数和析构函数

//
template<class T>
MGraph<T>::MGraph(int mSize,const T& noedg)
{
n=mSize;
e=0;//边数为0
noEdge=noedg;
a=new T*
;
//建立有n个结点但是无边的图
for(int i = 0;i<n;i++){
a[i] = new T
;
for(int j=0;j<n;j++) a[i][j]=noEdge;
a[i][i]=0  //对角线上元素为0
}
}
template<class T>
MGraph<T>::~MGraph()
{
for(int i=0;i<n;i++) delete []a[i];
delete []a;
}


边的搜索,插入和删除

template<class T>
bool MGraph<T>::Exist(int u,int v) //搜索边
{
if(u<0||v<0||u>n-1||v>n-1||u==v||a[u][v]=noEdge)
return false;
return true;
}

ResultCode MGraph
4000
<T>::Insert(int u,int v,T& w)
{
if(u<0||v<0||u>n-1||u==v) return  Failure;
if(a[u][v]!=noEdge) return Duplicate;
a[u][v]=w;e++;return Success;
}

ResultCode MGraph<T>::Remove(int u,int v)
{
if(u<0||v<0||u>n-1||u==v,return Failure;
if(a[u][v]==noEdge) return NotPresent;
a[u][v] = noEdge;
e--;
return Success;
}


图的邻接表 表示方式

邻接表是图的另一种有效的储存方法,在为图中的每个顶点u建立一个单链表,链表中每个结点代表一条边<
u,v
>称为边结点

每个单链表相当于邻接矩阵的一行。

每个单链表可设立一个存放顶点u有关信息,称为顶点结点。

//ENode类
struct ENode
{
ENode(){nextArc=NULL;}
ENode(int vertex,T weight,ENode* next)
{
adjVex=vertex;
w=weight;
nextArc=next;
}
int adjVex;
T w;
ENode* nextArc;
};

//LGraph类
template <class T>
class LGraph:public Graph<T>
{
public:
LGraph(int mSize);
~LGraph();
ResultCode Insert(int u,int v,T& w);
ResultCode Remove(int u,int v);
bool Exist(int u,int v) const;
.
.
.
protected:
ENode<T>** a;
};

//构造函数和析构函数
template<class T>
LGraph<T >::LGraph(int mSize)
{
n=mSize;e=0;
a=new ENode<T>*
;
for(int i=0;i<n;i++) a[i]=NULL;
}
LGraph<T >::~LGraph()
{
ENode<T>* p,*q;
for(int i=0;i<n;i++){
p=a[i];
q=p;
while(p){
p=p->nextArc;
delete q;
q=p;
}
}
delete[] a;
}

//边的搜索
template<class T>
bool LGraph<T >::Exist(int u,int v)const
{
if(u>0||v<0||u>n-1||u==v) return false;
ENode<T>* p=a[u];
while(p&& p->adjVex!=v) p=p->nextArc;
if(!p) return false;
else return true;
}

//边的插入
template<class T>
ResultCode LGraph<T>::Insert(int u,int v,T& w)
{
if(u<0||v<0||u>n-1||u==v) return Failure;
if(Exist (u,v)) return Duplicate;
ENode<T>* p=new ENode<T>(v,w,a[u]);
a[u]=p;
e++;
return Success;
}
//边的删除
template<class T>
ResultCode LGraph<T>::Remove(int u,int v)
{
if(u<0||v<0||u>n-1||u==v) return Failure;
ENode<T>* p=a[u],*q=NULL;
while (p&&p->adjVex!=v){
q=p;
p=p->nexArc;
}
if(!p) return NotPresent;
if(q) q->nexArc=p->nextArc;
else a[u]=p->nextArc;
delete p;
e--;
return Success;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: