zoukankan      html  css  js  c++  java
  • 数据结构--图的定义和存储结构

    图的定义

    图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成。注意:在图结构中,不允许没有顶点,在定义中,如果V是顶点的集合,则强调了顶点集合V的有穷非空。

    在图中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。

    图的存储结构

    邻接矩阵

    考虑到图是由顶点和边或者弧两部分组成的。合在一起比较困难,那就自然地考虑到分两个结构来分别存储。顶点不分大小、主次,所以用一个一位数组来存储是很不错的选择。而边或者弧是顶点与顶点之间的关系,一维搞不定,那就考虑用一个二维数组来存储。

    对于带权值的图,可以令不可达的边的权值为无穷大。利用这个无穷大代表两个顶点不可达。

     邻接矩阵结构代码

    //为了简单,默认顶点为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("读取顶点和边的数目...
    ");
    	scanf("%d,%d", &G->numVertexes, &G->numEdges);
    
    	//输入顶点信息
    	printf("读取顶点信息...
    ");
    	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和对应的权值...
    ");
    	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

     邻接表

    回忆在树的存储结构中,降到了一种孩子表示法,将这种数组与链表相结合的存储方法称为邻接表。

    注意上图的数组称为顶点表,链表为边表结点。

     对于有向图,其实更加简单,但是有向图的每一个顶点分为入度和出度。

    邻接表结构代码:

    #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("读取顶点和边数目...
    ");
    	scanf("%d%d", &G->numVertexs, &G->numEdges);
    	
    	printf("读取顶点...
    ");
    	for(k = 0; k < G->numVertexs; k++)
    	{
    		scanf("%d", &G->adjList[k].data);
    		G->adjList[k].firstEdge = NULL;
    	}
    	
    	printf("读取边信息...
    ");
    	//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
  • 相关阅读:
    jQuery教程1,隐藏p标签
    Google 和 Microsoft 对 jQuery 的支持都很好。
    在编辑器中自动换行
    调用存储过程的一些方法
    jQuery教程2隐藏p标签内容按钮
    文件的复制,移动,创建
    网站中access数据库的备份和恢复
    修改文件名称
    生成静态网页,函数,引用过程
    网页中打印文本文件
  • 原文地址:https://www.cnblogs.com/stemon/p/4596128.html
Copyright © 2011-2022 走看看