图的概念与遍历

1.线性表中的数据元素叫元素;树中数据元素叫结点;图中数据元素叫顶点。(线性表和树可以为空,图不可以为空)


2.树中根结点到任意结点的路径是唯一的,但是图中顶点与顶点之间的路径却是不唯一的。

路径长度是路径上的边或弧的数目。

第一个顶点到最后一个顶点系相同的路径称为回路或环。序列中顶点不重复出现的路径称为简单路径。除了第一个顶点和最后一个顶点外,其余顶点不重复出现的回路称为简单回路或简单环。

 

3.无向图中,若顶点v到顶点v’有路径,则称v和v’是连通的。若对于图中任意两个顶点都是连通的,称图是连通图。无向图中的极大连通子图称为连通分量。(无向图由顶点和边构成)

连通分量:(子图、子图是连通的、子图含有极大顶点数、具有极大顶点数的连通子图包含依附于这些顶点的所有边)

 

4.有向图中,如果对于每一对顶点v、u(v!=u),从v到u和从u到v都存在路径,则称图是强连通图。有向图中的极大强连通子图称为有向图的强连通分量。(有向图由顶点和弧构成)

 

5.一个连通图的生成树是一个极小的连通子图,它含有图中全部的n个顶点,但只有足以构成一棵树的n-1条边。(如果一个图有n个顶点和小于n-1条边,则是非连通图;如果多余n-1条边,必定构成一个环。不管有n-1条边并不一定是生成树)

 

6.如果一个有向图恰好有一个顶点入度为0,其余顶点的入度均为1,则是一颗有向树。

 

7.图的存储:邻接矩阵、邻接表、十字链表、邻接多重表、边集数组。

(邻接矩阵时间复杂度O(N+N^2+E),邻接表时间复杂度O(N+E))

(把数组与链表相结合的存储方法称为邻接表。)


邻接表的处理方法:

(1)图中顶点用一个一维数组存储,对于顶点数组中,每个数据元素还需要存储指向第一个邻接点的指针,以便于查找该顶点的边信息。

(2)图中每个顶点的所有邻接点构成一个线性表,由于邻接点的个数不定,所以用单链表存储。

(3)顶点表由data和firstedge两个域表示,data数据域存储顶点信息,firstedge指针域指向边表第一个结点。边表结点由adjvex和next域组成,adjvex是邻接点域存储某顶点的邻接点在顶点表中的下标,next则存储指向边表中下一个结点的指针。

 

8.十字链表把邻接表与逆邻接表结合起来。既可以找到v为尾的弧,也可以找到v为头的弧,因而可以容易求得出度和入度。创建图算法的时间复杂度是和邻接表相同的。


9.(1)邻接矩阵DFS

typedef int Boolean;
Boolean visited[MAX];//访问标志的数组 
//邻接矩阵的深度优先递归算法 
void DFS(MGraph G,int i) {
	int j;
	visited[i]=TRUE;
	printf("%c",G.vexs[i]);//打印顶点 
	for(j=0;j<G.numVertexes;j++)
		if(G.arc[i][j]==1 && !visited[j])
			DFS(G,j);		//对访问的邻接顶点递归调用 
}
//邻接矩阵的深度遍历操作 
void DFSTraverse(MGraph G) {
	int i;
	for(i=0;i<G.numVertexes;i++)
		visited[i]=FALSE;//初始所有顶点状态都是未访问过的状态
	for(i=0;i<G.numVertexes;i++)
		if(!visited[i])//对未访问的顶点调用DFS,若是连通图只执行一次
			DFS(G,i);
}

(2)邻接表DFS

//邻接表的深度优先递归算法 
void DFS(GraphAdjList GL,int i) {
	EdgeNode *p;
	visited[i]=TRUE;
	printf("%c",GL->adjList[i].data);//打印顶点 
	p=GL->adjList[i].firstedge;
	while(p) {
		if(!visited[p->adjvex])
			DFS(Gl,p->adjvex);
		P=P->next;
	}	
}
//邻接表的深度遍历操作 
void DFSTraverse(GraphAdjList GL) {
	int i;
	for(i=0;i<GL->numVertexes;i++)
		visited[i]=FALSE;
	for(i=0;i<GL->numVertexes;i++)
		if(!visited[i])
			DFS(GL,i);
}

(3)
//邻接矩阵的广度遍历操作 
void BFSTraverse(MGraph G) {
	int i,j;
	Queue Q;
	for(i=0;i<G.numVertexes;i++)
		visited[i]=false;
	InitQueue(&Q);		//初始化一辅助用的队列 
	for(i=0;i<G.numVertexes;i++) { 	//对每一个顶点做循环 
	if(!visited[i]) {			//若是未访问就做处理 
		visited[i]=TRUE;		//设置当前顶点访问过 
			printf("%c",G.vexs[i]);	//打印顶点 
			EnQueue(&Q,i);			//将此队列入队 
			while(!QueueEmpty(Q)) {	//若当前队列不为空 
				DeQueue(&Q,&i);		//将队列元素出队列,赋值给i 
				for(j=0;j<G.numVertexes;j++) {
				if(G.arc[i][j]==1 && !visited[j]) {//判断其他顶点若与当前顶点存在边且未被访问过 
					visited[j]=TRUE;	//将找到的此点标记已访问 
					printf("%c",G.vexs[j]);//打印 
					EnQueue(&Q,j);			//将找到的此顶点入队列 
					}
				}
			}
		}
	}
}

(4)

//邻接表的广度遍历操作 
void BFSTraverse(GraphAdjList GL) {
	int i;
	EdgeNode *p;
	Queue Q;
	for(i=0;i<GL->numVertexes;i++)
		visited[i]=FALSE;
	InitQueue(&Q);		//初始化一辅助用的队列 
	for(i=0;i<GL->numVertexes;i++) { 	//对每一个顶点做循环 
		if(!visited[i]) {			//若是未访问就做处理 
			visited[i]=TRUE;		//设置当前顶点访问过 
			printf("%c",GL->adjList[i].data);	//打印顶点 
			EnQueue(&Q,i);			//将此队列入队 
			while(!QueueEmpty(Q)) {	//若当前队列不为空 
				DeQueue(&Q,&i);		//将队列元素出队列,赋值给i 
				p=GL->adjList[i].firstedge;
				while(p) {
					if(!visited[p->adjvex]) {
						visited[p->adjvex]=TRUE;	//将找到的此点标记已访问 
						printf("%c",GL->adjList[p->adjvex].data);//打印 
						EnQueue(&Q,p->adjvex);			//将找到的此顶点入队列 
					}	
					p=p->next;
				}
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值