数据结构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; }
相关文章推荐
- POJ1743 Musical Theme 后缀数组
- 数据结构实验之查找一:二叉排序树【OJ--3373】
- 数据结构(一):查找和排序
- 2015年大二上-数据结构-数组与广义表(2)-2.压缩存储的对称矩阵的运算
- 《数据结构》重点概念复习
- 2015年大二上-数据结构-数组与广义表(2)-1.对称矩阵的压缩存储及基本运算
- 线性表
- 一步步写平衡二叉树(AVL树)
- 第十三周--数据结构- Floyd算法验证
- 第15周SHH数据结构-【项目1-验证算法】
- 第14周SHH数据结构-【项目1-(3)验证二叉排序树相关算法】
- 第14周SHH数据结构-【项目3-是否二叉排序树?】
- 第14周SHH数据结构-【项目2-二叉树排序树中查找的路径】
- 第14周SHH数据结构-【项目1-(2)验证分块查找算法】
- 【项目3- 归并排序算法的改进】
- 第14周SHH数据结构-【 项目1-(1)验证折半查找算法 】
- 第9周SHH数据结构-【项目4-广义表算法库及应用(2)】
- 【项目4 - 英文单词的基数排序】
- *第十六周*数据结构实践项目二【大数据集上排序算法性能的体验】
- 第9周SHH数据结构-【项目4-广义表算法库及应用(1)】