图:图是一种数据结构,由顶点的有穷非空集合和顶点之间边的集合组成,表示为G(V,E),V表示为顶点的集

合,E表示为边的集合。

首先肯定是要对图进行存储,然后进行一系列的操作,下面对图的两种存储方式邻接矩阵和邻接表尽行介绍。

(一)、邻接矩阵存储:

用两个数组分别进行存储数据元素(顶点)的信息和数据元素之间的关系(边或弧)的信息。

存储顶点:用一个连续的空间存储n个顶点。

存储顶点之间的边:将由n个顶点组成的边用一个n*n的矩阵来存储,如果两个顶点之间有边,则表示为1,否

则表示为0。

下面用代码来实现邻接矩阵的存储:

#define SIZE 10class Graph
{
public:Graph(){MaxVertices = SIZE;NumVertices = NumEdges = 0;VerticesList = new char[sizeof(char)*MaxVertices];Edge = new int*[sizeof(int*)*MaxVertices];int i,j;for(i = 0;i<MaxVertices;i++)Edge[i] = new int[sizeof(int)*MaxVertices];for(i = 0;i<MaxVertices;i++){for(j = 0;j<MaxVertices;++j)Edge[i][j] = 0;}}void ShowGraph(){int i,j;cout<<"  ";for(i = 0;i<NumVertices;i++)cout<<VerticesList[i]<<" ";cout<<endl;for(i = 0;i<NumVertices;i++){cout<<VerticesList[i]<<" ";for(j = 0;j<NumVertices;j++)cout<<Edge[i][j] <<" ";cout<<endl;}cout<<endl;}int GetVertexPos(char v){int i;for(i = 0;i<NumVertices;i++){if(VerticesList[i] == v)return i;}return -1;}~Graph(){Destroy();}void Insert(char v){if(NumVertices < MaxVertices){VerticesList[NumVertices] = v;NumVertices++;   }}void InsertEdge(char v1,char v2)  {int i,j;int p1 = GetVertexPos(v1);  int p2 = GetVertexPos(v2);if(p1 == -1 || p2 == -1)return ;Edge[p1][p2] = Edge[p2][p1] = 1;NumEdges++;  }void RemoveEdge(char v1,char v2){int p1 = GetVertexPos(v1);int p2 = GetVertexPos(v2);if(p1 == -1 || p2== -1)return;if(Edge[p1][p2] == 0) return;Edge[p1][p2] = Edge[p2][p1] = 0;NumEdges--;}void Destroy(){delete[] VerticesList;VerticesList = NULL;for(int i = 0;i<NumVertices;i++){delete Edge[i];Edge[i] = NULL;}delete[] Edge;Edge = NULL;MaxVertices = NumVertices = 0;}void RemoveVertex(char v){int i,j;int p = GetVertexPos(v);int reNum = 0;if(p == -1)return;for(i = p;i<NumVertices-1;i++) {VerticesList[i] = VerticesList[i+1];}for(i = 0;i<NumVertices;i++){if(Edge[p][i] != 0)reNum++;}for(i = p;i<NumVertices-1;i++){for(j = 0;j<NumVertices;j++){Edge[i][j] = Edge[i+1][j];}}for(i = p;i<NumVertices;i++){for(j = 0;j<NumVertices;j++)Edge[j][i] = Edge[j][i+1];}NumVertices--;NumEdges = NumEdges - reNum;}
private:int MaxVertices;int NumVertices;int NumEdges;char *VerticesList;int **Edge;
};

上面的类中的数据有定义最大的顶点的个数(MaxVertices),当前顶点的个数(NumVertices),当前边的个数

(NumEdges),保存顶点的数组,保存边的数组。其中的方法是(1)构造函数:对定义的数据进行初始化。(2)显

示构造的图的信息的函数。(3)得到顶点位置信息的函数。(4)析构函数:调用销毁函数。(5)插入顶点函数。

(6)插入边的函数。(7)删除边的函数。(8)销毁函数,释放开辟的内存空间。(9)删除顶点函数。

(二)、邻接表存储:

邻接表是图的一种链式存储结构。用数组存储顶点,用链表存储和顶点相关联的边,边值为当前顶点在数组中的下

标。用如下图可以表示邻接表的存储方式:

下面用代码来实现邻接表的存储:

#define SIZE 10
typedef char T;
struct Edge
{Edge(int v):destvalue(v),link(NULL){}int destvalue;Edge *link;
};
struct Vertex
{Vertex():list(NULL){}T data;Edge *list;
};
class GraphLnk
{
public:GraphLnk();~GraphLnk(){}void InsertVertex(T v);void InsertEdge(T v1,T v2);int GetVertexI(T v);void ShowGraph();void RemoveEdge(T v1,T v2);void RemoveVertex(T v);void DestroyGraph();
private:int MaxVertex;int NumVertex;int NumEdge;Vertex *VertexTable;
};GraphLnk::GraphLnk()
{MaxVertex = SIZE;NumVertex = NumEdge = 0;VertexTable = new Vertex[MaxVertex];
}
void GraphLnk::InsertVertex(T v)
{if(NumVertex >= MaxVertex)return;VertexTable[NumVertex++].data = v;
}
void GraphLnk::ShowGraph()
{int i;for(i = 0;i<NumVertex;i++){cout<<i<<" "<<VertexTable[i].data<<":->";Edge *p = VertexTable[i].list;while(p != NULL){cout<<p->destvalue<<"->";p = p->link;}cout<<"nul"<<endl;}cout<<endl;
}
int GraphLnk::GetVertexI(T v)
{int i;for(i = 0;i<NumVertex;i++){if(VertexTable[i].data == v)return i;}return -1;
}
void GraphLnk::InsertEdge(T v1,T v2)
{int p1 = GetVertexI(v1);int p2 = GetVertexI(v2);if(p1 == -1 || p2 == -1)return;//v1 -> v2Edge *ed = new Edge(p2);ed->link = VertexTable[p1].list;VertexTable[p1].list = ed;//v2 -> v1ed = new Edge(p1);ed->link = VertexTable[p2].list;VertexTable[p2].list = ed;NumEdge++;
}void GraphLnk::RemoveEdge(T v1,T v2)
{int p1 = GetVertexI(v1);int p2 = GetVertexI(v2);if(p1 == -1 || p2 == -1)return;Edge *q = NULL;              //标识要删除边链表的前一个Edge *p;
p = VertexTable[p1].list;    //从链表开头开始//查找v2所在位置while(p != NULL && p->destvalue != p2){q = p;p = p->link;}if(p == NULL)          //两个顶点之间没有边的存在¨return;//找到所要删除的边if(q == NULL)      //所要删除的为链表开头
        {VertexTable[p1].list = p->link;}else{q->link = p->link;}delete p;p = NULL;q = NULL;p = VertexTable[p2].list;while(p->destvalue != p1){q = p;p = p->link;}if(q == NULL){VertexTable[p2].list = p->link;}else{q->link = p->link;}delete p;p = NULL;NumEdge--;
}void GraphLnk::RemoveVertex(T vertex)
{int v  = GetVertexI(vertex);if(v == -1)return;//删除和结点相关的边Edge*p=VertexTable[v].list;Edge *s;Edge *t = NULL;int k;while(p != NULL){k = p->destvalue;s = VertexTable[k].list;while(s != NULL&&s->destvalue != v){t = s;s = s->link;}if(s != NULL){if(t == NULL)     //第一个结点
            {VertexTable[k].list = s->link;}else{t->link = s->link;}delete s;s = NULL;}VertexTable[v].list = p->link;delete p;p = VertexTable[v].list;}/*删除结点,用最后一个结点覆盖要删除的结点,并把和最后一个结点相关联的边的下标改正*/NumVertex--;VertexTable[v].data = VertexTable[NumVertex].data; VertexTable[v].list = VertexTable[NumVertex].list;
s = VertexTable[v].list;while(s != NULL){k = s->destvalue;p = VertexTable[k].list;while(p != NULL){if(p->destvalue == NumVertex)
            {p->destvalue = v;break;}p = p->link;}s = s->link;}
}void GraphLnk::DestroyGraph()
{Edge *p;for(int i = 0;i<NumVertex;i++){p = VertexTable[i].list;while(p != NULL){VertexTable[i].list = p->link;delete p;p = VertexTable[i].list;}}delete []VertexTable;MaxVertex = NumEdge = NumVertex = 0;
}

在代码实现的过程中,先定义出顶点和边的数据结构,然后在类中定义了最大顶点数,当前顶点的个数,当前的

边的个数,顶点类型的数组,还有在类中进行了函数的声明,包括(1)构造函数。(2)析构函数。(3)插入顶点

函数。(4)插入边函数。(5)得到顶点位置的函数。(6)显示构造出的图的信息函数。(7)删除边函数。(8)

删除顶点函数。(9)销毁函数。

转载于:https://www.cnblogs.com/XNQC1314/p/9076698.html

图的两种存储方式---邻接矩阵和邻接表相关推荐

  1. 图的两种存储形式(邻接矩阵、邻接表)

    图可以使用两种存储结构,分别是邻接矩阵和邻接表. 注意:一个图所对应的邻接矩阵唯一,所对应的邻接表不唯一 一.邻接矩阵 邻接矩阵以矩阵的形式存储图所有顶点间的关系.邻接矩阵具有以下特点: 1.邻接矩阵 ...

  2. 三十张图片让你彻底弄明白图的两种遍历方式:DFS和BFS

    1 引言   遍历是指从某个节点出发,按照一定的的搜索路线,依次访问对数据结构中的全部节点,且每个节点仅访问一次.图的遍历.遍历过程中得到的顶点序列称为图遍历序列. 2 深度优先搜索 2.1 算法思想 ...

  3. lisp遍历表中所有顶点_三十张图片让你彻底弄明白图的两种遍历方式:DFS和BFS...

    1 引言   遍历是指从某个节点出发,按照一定的的搜索路线,依次访问对数据结构中的全部节点,且每个节点仅访问一次.   在二叉树基础中,介绍了对于树的遍历.树的遍历是指从根节点出发,按照一定的访问规则 ...

  4. 构建复杂网络的几种方法(邻接矩阵,邻接表,十字链表,邻接多重表)

    目录 1. 数据结构 线性结构 非线性结构 2. 复杂网络的数组表示 3. 复杂网络的邻接表表示 4. 邻接矩阵与邻接表的比较 5. 复杂网络的其他表示方法 逆邻接表 十字链表 邻接多重表 前向星 链 ...

  5. 分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_数据结构与算法:三十张图弄懂「图的两种遍历方式」...

    原创: 进击的HelloWorld1 引言遍历是指从某个节点出发,按照一定的的搜索路线,依次访问对数据结构中的全部节点,且每个节点仅访问一次. 在二叉树基础中,介绍了对于树的遍历.树的遍历是指从根节点 ...

  6. 有向图的广度优先遍历_图的两种遍历方式

    1 引言 遍历是指从某个节点出发,按照一定的的搜索路线,依次访问对数据结构中的全部节点,且每个节点仅访问一次. 在二叉树基础中,介绍了对于树的遍历.树的遍历是指从根节点出发,按照一定的访问规则,依次访 ...

  7. c++层次遍历_数据结构与算法,弄懂图的两种遍历方式

    1 引言   遍历是指从某个节点出发,按照一定的的搜索路线,依次访问对数据结构中的全部节点,且每个节点仅访问一次.  在二叉树基础中,介绍了对于树的遍历.树的遍历是指从根节点出发,按照一定的访问规则, ...

  8. 深度优先遍历访问的边集合_数据结构与算法: 三十张图弄懂「图的两种遍历方式」...

    1 引言 遍历是指从某个节点出发,按照一定的的搜索路线,依次访问对数据结构中的全部节点,且每个节点仅访问一次. 在二叉树基础中,介绍了对于树的遍历.树的遍历是指从根节点出发,按照一定的访问规则,依次访 ...

  9. 计算机图形学--图像的两种存储方式:点阵存储和矢量存储

    计算机可以使用两种方式来显示图像: 一:点阵文件:又名:取样图像.点阵图像.位图图像.从现实世界中通过数字化设备(扫描仪)获取的图.点阵文件缩放会失真,保存起来占用空间比较大. 主要的参数有1. 图像 ...

最新文章

  1. 目前的Android恶意软件分类
  2. C语言经典例85-判断一个素数能被几个9整除
  3. 让代码看起来更舒服, 修改VS颜色样式
  4. CMA-ES 算法初探
  5. ORACLE同义词源库锁表导致目标库删除操作报ora 02055 02049 02063 06512
  6. [渝粤教育] 中国地质大学 电力系统保护原理 复习题 (2)
  7. JavaScript 学到什么程度可以学 Node.js?
  8. 【每日算法Day 70】图解算法:小学生都会的数块数问题,你会吗?
  9. emacs工程管理,cedet ede插件自动构建Make,Automake
  10. sklearn库里几种回归模型
  11. 2019华为机试题 消息扩散
  12. unity 2d文字跟随主角移动_用Unity制作GalGame/视觉小说游戏的模型素材与插件推荐...
  13. vscode——VScode 中 使用 comment translate翻译 插件
  14. c开头英文语言,字母C开头的英文名
  15. App inventor打地鼠
  16. 在EXCEL表格中如何进行快速换行
  17. warning: iteration xxxu invokes undefined behavior [-Waggressive-loop-optimizations]
  18. 记录学习技巧--如何翻阅或学习英文文档
  19. linux中从内存解析xml格式的库,Linux下使用libxml库解析xml文件
  20. 什么是大病医保?是商业保险吗?包括哪些病?怎么办理?

热门文章

  1. 网络名称空间 实例研究 veth处于不同网络的路由问题
  2. ios之开发者须知常见简写英文代表的含义
  3. Java中使用Observer接口和Observable类实践Observer观察者模式
  4. Java多线程之ReentrantReadWriteLock
  5. 2014-07-23 利用ASP.NET自带控件实现单文件上传与下载
  6. 5月下旬全球域名解析服务商TOP15:万网居第15
  7. C#DataGridView添加序号
  8. 笑傲江湖,独孤求败-NetScaler MAS应用交付神功详解
  9. wordpress图片水印插件DX-Watermark
  10. Android adb opendir failed ,permission denied