数据结构--图的定义和存储结构
2015-06-23 19:06
573 查看
图的定义
图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成。注意:在图结构中,不允许没有顶点,在定义中,如果V是顶点的集合,则强调了顶点集合V的有穷非空。
在图中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。
图的存储结构
邻接矩阵
考虑到图是由顶点和边或者弧两部分组成的。合在一起比较困难,那就自然地考虑到分两个结构来分别存储。顶点不分大小、主次,所以用一个一位数组来存储是很不错的选择。而边或者弧是顶点与顶点之间的关系,一维搞不定,那就考虑用一个二维数组来存储。
![](http://images0.cnblogs.com/blog2015/398159/201506/231903187524418.png)
对于带权值的图,可以令不可达的边的权值为无穷大。利用这个无穷大代表两个顶点不可达。
邻接矩阵结构代码
无向图的创建代码:
无向图的边的二维数组是一个对称矩阵,有向图的创建更加简单。
测试代码:
试验数据:
邻接表
回忆在树的存储结构中,降到了一种孩子表示法,将这种数组与链表相结合的存储方法称为邻接表。
![](http://images0.cnblogs.com/blog2015/398159/201506/231939105644959.png)
注意上图的数组称为顶点表,链表为边表结点。
对于有向图,其实更加简单,但是有向图的每一个顶点分为入度和出度。
![](http://images0.cnblogs.com/blog2015/398159/201506/231942570024449.png)
![](http://images0.cnblogs.com/blog2015/398159/201506/231944171277403.png)
邻接表结构代码:
邻接表创建有向图代码:
在插入边表结点的时候,采用头插法更加简单一些。
测试代码:
测试数据:
图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成。注意:在图结构中,不允许没有顶点,在定义中,如果V是顶点的集合,则强调了顶点集合V的有穷非空。
在图中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。
图的存储结构
邻接矩阵
考虑到图是由顶点和边或者弧两部分组成的。合在一起比较困难,那就自然地考虑到分两个结构来分别存储。顶点不分大小、主次,所以用一个一位数组来存储是很不错的选择。而边或者弧是顶点与顶点之间的关系,一维搞不定,那就考虑用一个二维数组来存储。
![](http://images0.cnblogs.com/blog2015/398159/201506/231903187524418.png)
对于带权值的图,可以令不可达的边的权值为无穷大。利用这个无穷大代表两个顶点不可达。
邻接矩阵结构代码
//为了简单,默认顶点为int类型,也就是v0,v1,v2等的那个下标 //权值为int类型 #define MAXVEX 100 #define INF 65535 typedef struct { int vexs[MAXVEX]; int arc[MAXVEX][MAXVEX]; int numVertexes, numEdges; }MGraph;
无向图的创建代码:
void CreateMGraph(MGraph *G) { //k为循环变量 int k = 0; //i,j代表顶点的下标 int i = 0; int j = 0; printf("读取顶点和边的数目...\n"); scanf("%d,%d", &G->numVertexes, &G->numEdges); //输入顶点信息 printf("读取顶点信息...\n"); for(k = 0; k < G->numVertexes; k++) { scanf("%d", &G->vexs[k]); } //初始化所有的边为无穷大 for(i = 0; i < G->numVertexes; i++) { for(j = 0; j < G->numVertexes; j++) { G->arc[i][j] = INF; } }//for int weight = 0; //获取权值的输入值 printf("读取边(vi,vj)中两个顶点的下表i、j和对应的权值...\n"); for(k = 0; k < G->numEdges; k++) { scanf("%d,%d,%d", &i, &j, &weight); G->arc[i][j] = weight; G->arc[j][i] = weight; }//for }//CreateMGraph()
无向图的边的二维数组是一个对称矩阵,有向图的创建更加简单。
测试代码:
void main(void) { freopen("in.txt", "r", stdin); MGraph mGraph; MGraph *pMGraph = &mGraph; CreateMGraph(pMGraph); fclose(stdin); return; }
试验数据:
//in.txt 4,5 0 1 2 3 0,1,10 0,2,2 0,3,7 1,2,8 2,3,5
邻接表
回忆在树的存储结构中,降到了一种孩子表示法,将这种数组与链表相结合的存储方法称为邻接表。
![](http://images0.cnblogs.com/blog2015/398159/201506/231939105644959.png)
注意上图的数组称为顶点表,链表为边表结点。
对于有向图,其实更加简单,但是有向图的每一个顶点分为入度和出度。
![](http://images0.cnblogs.com/blog2015/398159/201506/231942570024449.png)
![](http://images0.cnblogs.com/blog2015/398159/201506/231944171277403.png)
邻接表结构代码:
#define MAXVEX 100 typedef struct EdgeNode { int adjvex; int weight;//边的权重,用int表示 struct EdgeNode *next; }EdgeNode; typedef struct VertexNode { int data; EdgeNode *firstEdge; }AdjList; typedef struct { AdjList adjList[MAXVEX]; int numVertexs; int numEdges; }AdjGraph;
邻接表创建有向图代码:
void CreateAdjGraph(AdjGraph *G) { //统一规定,k用作循环变量 int k = 0; printf("读取顶点和边数目...\n"); scanf("%d%d", &G->numVertexs, &G->numEdges); printf("读取顶点...\n"); for(k = 0; k < G->numVertexs; k++) { scanf("%d", &G->adjList[k].data); G->adjList[k].firstEdge = NULL; } printf("读取边信息...\n"); //i,j用作表示顶点的下表,weight表示边的权重 int i = 0; int j = 0; int weight = 0; for(k = 0; k < G->numEdges; k++) { scanf("%d%d%d", &i, &j, &weight); EdgeNode *pEdgeNode = (EdgeNode*)malloc(sizeof(EdgeNode)); pEdgeNode->adjvex = j; pEdgeNode->weight = weight; pEdgeNode->next = NULL; //采用头插法,将这个边节点插入 pEdgeNode->next = G->adjList[i].firstEdge; G->adjList[i].firstEdge = pEdgeNode; /*无向图插入边信息 //对于无向图,这里要再次插入 EdgeNode *pEdgeNode = (EdgeNode*)malloc(sizeof(EdgeNode)); pEdgeNode->adjvex = i; pEdgeNode->weight = weight; pEdgeNode->next = NULL; //采用头插法,将这个边节点插入 pEdgeNode->next = G->adjList[j].firstEdge; G->adjList[j].firstEdge = pEdgeNode; */ } }//CreateAdjGraph
在插入边表结点的时候,采用头插法更加简单一些。
测试代码:
void main(void) { freopen("in.txt", "r", stdin); AdjGraph adjGraph; AdjGraph *pAdjGraph = &adjGraph; CreateAdjGraph(pAdjGraph); fclose(stdin); }
测试数据:
//in.txt 10 19 0 1 2 3 4 5 6 7 8 9 0 1 4 0 2 1 0 3 3 2 3 1 1 4 9 1 5 8 2 4 6 2 5 7 2 6 8 3 5 4 3 6 7 4 7 5 4 8 6 5 7 8 5 8 6 6 7 6 6 8 5 7 9 7 8 9 3
相关文章推荐
- 2-06. 数列求和
- 【数据结构】直接插入排序_哨兵位
- 数据结构基础(5)--C语言实现循环队列--静态
- Two Sum III - Data structure design数据结构设计
- 【数据结构】直接插入排序
- [数据结构]队列之链式队列的类模板实现
- 《数据结构》学习笔记--第一章绪论
- [数据结构]纸牌游戏——小猫钓鱼
- [数据结构]队列之顺序队列的类模板实现
- 递归与回溯:八皇后问题
- 数据结构学习之二叉树(面试易考题整理)
- 数据结构基础温故-1.线性表(上)
- 线性表-链表-数据结构java版
- 线性表-顺序表-数据结构java版
- 数据结构
- (数据结构)顺序表的建立,增删查改
- 数据结构基础(5)--队列和循环队列详解--静态方式
- 数据结构-图的遍历
- 数组实现栈的数据结构
- 函数类型的数据结构