python-数据结构与算法补充2


——《大话数据结构》的搬运工

第七章

图的定义

7.2.1各种图的定义

无向边:l两顶点间无方向,用无序偶对 ( v i , v j ) (v_i,v_j) (vi,vj)表示
无向图:任意两顶点之间的边都是无向边,则为无向图,顶点A和D,(A,D)或(D,A)
无向图 G 1 = ( V 1 , E 1 ) G_1=(V_1,{E_1}) G1=(V1,E1),顶点结合 V 1 = A , B , C , D V_1={A,B,C,D} V1=A,B,C,D,边几何 E 1 = ( A , B ) , ( B , C ) , ( D , A ) , ( A , C ) E_1={(A,B),(B,C),(D,A),(A,C)} E1=(A,B),(B,C),(D,A),(A,C)
有向边(弧):两顶点间有方向,用有序偶对 < v i , v j > <v_i,v_j> <vi,vj>表示
有向图:任意两顶点之间的边都是有向边,则为有向图,顶点A和D,<A,D>
有向图: G 2 = ( V 2 , E 2 ) G_2=(V_2,{E_2}) G2=(V2,E2),顶点结合 V 2 = A , B , C , D V_2={A,B,C,D} V2=A,B,C,D,边几何 E 2 = < A , B > , < B , C > , < D , A > , < A , C > E_2={<A,B>,<B,C>,<D,A>,<A,C>} E2=<A,B>,<B,C>,<D,A>,<A,C>
简单图:没有自身到自身的边
无向完全图:任意两个顶点之间都存在无向边(不是路径),n个顶点有 n ( n + 1 ) 2 \frac{n(n+1)}{2} 2n(n+1)条边
有向完全图:任意两个顶点之间都存在有向边(互为相反的弧),n个顶点有n(n+1)条边
网:带权的图,每个边有各自的权重

7.2.2图的顶点和边间关系

无向图:
顶点的度是和顶点相关联的边的数目,TD(V)
无向图的边数是所有顶点度的和的一半
有向图:——说法有问题?
以顶点v为头的弧的数目,为V的入度,ID(V)
以顶点V为尾的弧的数目,为V的出度,OD(V)
顶点V的度为TD(V)=ID(V)+OD(V)
有向图的边数=所有顶点的入度=所有顶点的出度

无向图中某一顶点到另一个顶点的路径,为所经过顶点组成的顶点序列
有向图的路径也是有向的

回路(环):第一个顶点和最后一个顶点相同
简单回路:除最后一个顶点和第一个顶点外,路径不经过重复顶点

7.2.3连通图相关术语

连通图:图中任意两个顶点都是连通(路径)的
无向图中的极大连通子图称为连通分量:

  • 子图(单纯连通子图不叫做连通分量)
  • 子图是连通的
  • 连通子图含有极大顶点数
  • 具有极大顶点数的连通子图包含依附于这些顶点的所有边

有向图中,任意一对顶点,互有路径可以到达,称为强连通图(不是有向完全图)
有向图中的极大强连通子图,称为有向图的强连通分量
给的例子有问题吧?

连通图的生成树

极小的连通子图叫做连通图的生成树。
生成树(极小连通子图)含有图中全部的n个顶点,但只有足以构成一棵树的n-1条边

n个顶点,小于n-1个边,是非连通图
n个顶点,大于n-1个边,必有环(不同于无向完全图)

在这里插入图片描述

7.4图的存储结构

7.4.1邻接矩阵

用两个数组表示图。一维数组存储图中的顶点信息。二维数组(邻接矩阵)存储图中的边的信息
n个顶点,则有一个nXn的矩阵
无向图的邻接矩阵是一个对称矩阵
网的邻接矩阵(带权的邻接矩阵):不存在的边用无穷表示

//邻接矩阵的结构
typedef char VertexType;
typedef in EdgeType;
#define MAXVEX 100
#define INFINITY 65535//用65536表示无穷
typedef struct
{
	VertexType vexs[MAXVEX];//定点表
	EdgeType arc[MAXVEX][MAXVEX];//邻接矩阵
	int numVertexes,numEdges;//顶点数和边数
}MGraph;
//邻接矩阵的表示
void CreateMGraph(MGraph* G)
{
	int i,j,k,w;
	printf("输入顶点数和边数:\n");
	scanf("%d,%d",&G-numVertexes,&G->numEdges);
	for(int i=0;i<G-numVertexes;i++)
	{
		scanf("%d",&G-vexs[i]);	
	}
	for( i=0;i<G-numVertexes;i++)
	{
		for( j=0;j<G-numVertexes;j++)
		{
			G->arc[i][j]=INFINITY;//邻接矩阵初始化
		}	
	}
	for(k=0;k<G->numEdges;k++)
	{
		printf("输入边(vi,vj)上的下标i和下标j和权重w:\n");
		scanf("%d,%d,%d",&i,&j,&w);
		G->arc[i][j]=w;
		G->arc[j][i]=G->arc[i][j];//构建无向图
	}
}

7.4.2邻接表

对于稀疏图,邻接矩阵浪费存储空间。
利用数组和链表相结合的存储方法称为邻接表

  • 利用一维数组存储顶点,每个数据元素都存储一个指向第一个临界点的指针,便于查找顶点的边信息
  • 每个顶点的所有邻接点构成一个线性表,利用单链表存储
    在这里插入图片描述

adjvex存储的是邻接下标

有向图邻接表见P229

typedef char VertexType;//顶点类型
typedef int EdgeType;//权值类型

typedef struct EdgeNode//边表结点
{
	int adjvex;//邻接点域,存储对应的下标
	EdgeType weight;//用于存储权值,非网图则不需要
	struct EdgeNode* next;//链域,指向下一个邻接点
}EdgeNode;

typedef struct VertexNode//顶点表结点
{
	VertexType data;//存储顶点信息
	EdgeNode* firstedge;//边表头结点
}VertexNode,AdjList[MAXVEX];//相当于是一个结构体数组别名

typedef struct//邻接表
{
	AdjList adjList;//相当于struct VertexNode adjList[MAXVEX],每个adjList[i]都有一个data和一个firstedge;
	int numVertexes,numEdges;//图中当前顶点数和边数
}GraphAdjList;
//建立图的邻接表结构
void CreateALGraph(GraphAdjList* G)//G包含一个adjList和当前顶点数和边数,一个adjList是struct VertexNode adjList[MAXVEX],每个adjList[i]都有一个data和一个firstedge;
{
	int i,j,k;
	EdgeNode* e;
	printf("输入顶点数和边数\n");
	scanf("%d,%d",&G->numVertexes,&G->numEdges);
	for(i=0;i<G->numVertexes;i++)//建立顶点表
	{
		scanf("%c",&G->adjList[i].data);//输入顶点信息,每个adjList[i]都有一个data和一个firstedge;
		G->adjList[i].firstedge=NUll;//先将边表置为空
	}
	
	//建立边表
	for(k=0;k<G->numEdges;k++)
	{
		printf("输入边(vi,vj)上的顶点序号\n");
		scanf("%d,%d"&i,&j);//输入边(vi,vj)上的顶点序号
		e=(EdgeNode*)malloc(sizeof(EdgeNode));//生成边表结点
		e->adjvex=j;//vi的邻接点vj邻接序号
		e->next=G->adjList[i].firstedge;//有点像插入链表的意思(将e指针指向当前顶点指向的结点)
		G->adjList[i].firstedge=e;//将当前顶点的指针指向e

		//因为树无向图,所以i,j互为邻接
		e=(EdgeNode*)malloc(sizeof(EdgeNode));//生成边表结点
		e->adjvex=i;//邻接序号为i
		e->next=G->adjList[j].firstedge;
		G->adjList[j].firstedge=e;
	}
}

注意上述插入链表的方法是头插法,边表示可以互换位置的

7.4.3十字链表

结合邻接表和逆邻接表,对有向图进行存储

//顶点表结构
data,firstin,firstout//firstin为入边表头指针,指向顶点的入边表的第一个结点,firstout表示出边表头指针,指向该顶点的出边表中的第一个结点
//边表结点结构
tailvex,headvex,headlink,taillink;//tailvex指弧起点在顶点表的下标,headvx是指弧终点在顶点表中的下标,headlink是指入表指针域,指向终点相同的下一条边,taillink指出边表指针域,指向起点相同(同一个顶点)的下一条边(出边)。若为网,则增加权重weight


书P233

7.4.4邻接多重表

无向图的邻接表更关注顶点,对于边的删除等操作比较麻烦。改进:仿照十字链表进行改造

ivex,ilink,jvex,jlink;//ivex和jvex是与某条边依附的两个顶点在顶点表中的下标,ilink指向依附顶点ivex的下一条边,jlink指向依附顶点jvex的下一条边

在这里插入图片描述

7.4.5边集数组

适用于对边依次进行处理的操作,见7.6.2克鲁斯卡尔kruskal算法
在这里插入图片描述

7.5图的遍历

从某一顶点出发,遍历图中其他顶点,其每个顶点只被访问一次。需要在遍历过程中,把访问过的顶点搭上标记,即设置一个数组vistied[n],初始为0,访问过后为1

7.5.1深度优先遍历DFS

深度优先是一个递归的过程,是一个树的前序遍历
邻接矩阵

typedef int Boolean;
Boolean visited[MAX];//访问标志的数组
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值