第七章 图【数据结构与算法】【精致版】

news2024/9/30 15:19:08

第七章 图【数据结构与算法】【精致版】

  • 前言
  • 版权
  • 第七章 图
    • 7.1 应用实例
    • 7.2图的基本概念
    • 7.3图的存储结构
      • 7.3.1邻接矩阵
        • **1-邻接矩阵.c**
        • **2-邻接矩阵plus.c**
      • 7.3.2 邻接表
        • **3-邻接表.c**
        • **4-邻接表plus.c**
      • 7.3.3 十字链表
      • 7.3.4多重链表
    • 7.4图的遍历
      • 7.4.1深度优先搜索遍历
        • **5-DFSAdjMatrix.c**
        • **6-DFSAdjList.c**
      • 7.4.2广度优先搜索遍历
        • **7-BFSAdjMatrix.c**
        • **8-BFSAdjList.c**
    • 7.5图的应用
      • 7.5.1最小生成树
        • **9-Prim.c**
      • 7.5.2 拓扑排序
        • **10-拓扑排序.c**
      • 7.5.3关键路径
      • 7.5.4最短路径
        • **11-单源最短路径.c**
        • **12-多源最短路径.c**
    • 6实例分析与实现
    • 7算法总结 贪心算法
  • 习题7
    • 3完成题 1 2 4 6
    • 4.算法设计题
      • (11)已知有向图以邻接表作为存储结构,编写算法判断该图中是否存在顶点V~i~到顶点V~j~,的简单路径,并输出该路径上的顶点。
  • 最后

前言

2023-11-6 17:07:13

以下内容源自《【数据结构与算法】【精致版】》
仅供学习交流使用

版权

禁止其他平台发布时删除以下此话
本文首次发布于CSDN平台
作者是CSDN@日星月云
博客主页是https://jsss-1.blog.csdn.net
禁止其他平台发布时删除以上此话

第七章 图

7.1 应用实例

城市交通问题

7.2图的基本概念

图的定义:图是由顶点集V和弧集R构成的数据结构,Graph=(V,R)
其中:
V={v|v∈ DataObject}
R={VR}
VR={<v,w>|P(v,w)且(v,w∈V)}
<v,w>表示从顶点v到顶点w的一条弧,称为“弧尾”,w为“弧头”
谓词P(v,w)定义了<u,w>的意义或信息,表示从到w的一条单向通道。
苦<v,w>∈VR,必有<w,v>∈VR,则以(v,w)代替这两个有序对,称v和w之间存在一条
有向图:由顶点集和弧集构成的图称为“有向图”。
无向图:由顶点集和边集构成的图称为“无向图"。

有向网或无向网:有向图或无向图中的弧或边带权后的图分别称为“有向网"或“无向网”

子图:设图G=(V|{VR})和图G’=(V’|{VR’}),且V’⊆V,VR’⊆VR,则称G’为G的子图。
完全图:图中有n个顶点、n(n-1)/2条边的无向图称为“完全图”。
有向完全图;图中有n个顶点、n(n-1)条弧的有向图称为“有向完全图”
稀疏图:假设图中有n个顶点e条边(或弧),若边(或弧)的个数e<nlogn,则称为“稀疏图”, 否则称为“稠密图
邻接点:若无向图中顶点v和w之间存在一条边(n,w),则称顶点v和w互为邻接点,称边 (r,w)依附于顶点n和w或边(v,w)与顶点v和w相关联。
顶点的度;在无向图中与顶点v关联的边的数目定义为v的度,记为TD(v)。
握手定理:可以看出,在无向图中,其总度数等于总边数的两倍。
对于有向图,若顶点v和w之间存在一条弧<u,w>,则称顶点v邻接到顶点w,顶点v邻接自 顶点v,称弧<v,w>与顶点u和w相关联。
以v为尾的弧的数目定义为v的出度,记为OD(v)。
以为头的弧的数目定义为v的入度,记为ID(v)。
顶点的度(TD)=出度(OD)+入度(ID)。
可以看出,在有向图中,其总人度、总出度和总强数相等
路径:设用G=(V|{VR}中的{u=vi,0,vi,1,…,vi,m=w}顶点序列中,有(vi,j-1,vi,j)∈VR(1<=j<=m),则称从顶点u到顶点w之间存在一条路径。路径上边的数目称为“路径长度”,有向图的路径也是有向的。
简单路径:顶点不重复的欧种称为“简单路径“
回路:首尾顶点相同的路径称为“回路“
简单回路:除了首尾顶点,中间任何一个顶点不重复的问路称为“简单回路”
连通图:在无向图中,若顶点Vi到Vj有路径存在,则称Vi和Vj是连通的。若无向图中任意两个顶点之间都有路径相通,即是连通的,则称此图为连通图,否则,称其为非连通图
无向图中各个极大连通子图称为该图的“连通分量
强连通图:在有向图中,若任意两个顶点之间都存在一条有向路径,则称此有向图为“强连通图”;否则,称其为“非强连通图”。
有向图中各个极大强连通子图称为该图的强连通分量
生成树:包含连通图中全部项点的极小连通子图称为该图的“生成树”,即假设一个连通图有n个顶点和e条边,其中n个顶点和n-1条边构成一个极小连通子图,该极小连通子图为此连通图的生成树。对非连通图,由各个连通分量的生成树构成的集合称为该非连通图的“生成森林

7.3图的存储结构

7.3.1邻接矩阵

图的邻接矩阵是表示顶点之间的相邻关系的矩阵,是顺序存储结构。
设图G是一个具有n个顶点的图,它的顶点集合V={v0,v1,v2,…,vn-1}则顶点之间的关系可用如下形式的矩阵A来描述,即矩阵A中每个元素A[i][j]满足

			{	1	若<v~i~,v~j~>或(v~i~,v~j~)∈VR
A[i][j] = 	{
			{	0	反之

对于带权图(网),邻接矩阵A中每个元素A[i][j]满足

			{	weight	若<v~i~,v~j~>或(v~i~,v~j~)∈VR
A[i][j] = 	{
			{	∞	反之

邻接矩阵的数据类型描述为:

#include<stdio.h> 
#include<stdlib.h>
#define MAXVEX 20				//最大顶点个数		
#define INFINITY 32768			//表示极大值 
typedef int Vextype;  
typedef struct{
	int arcs[MAXVEX][MAXVEX];	//边(或弧)信息
	Vextype vex[MAXVEX];		//顶点信息,顶点类型根据实际情况自行定义
	int vexnum;					//顶点数目
	int arcnum;					//边(或弧)数目
}AdjMatrix;//邻接矩阵
1-邻接矩阵.c

只针对无向网

//邻接矩阵的数据类型描述为:
#include<stdio.h> 
#include<stdlib.h>
#define MAXVEX 20				//最大顶点个数		
#define INFINITY 32768			//表示极大值 
typedef int Vextype;  
typedef struct{
	int arcs[MAXVEX][MAXVEX];	//边(或弧)信息
	Vextype vex[MAXVEX];		//顶点信息,顶点类型根据实际情况自行定义
	int vexnum;					//顶点数目
	int arcnum;					//边(或弧)数目
}AdjMatrix;//邻接矩阵
//【算法7.1】用邻接矩阵创建无向网
void Create(AdjMatrix *G){
	int i,j,k,weight,vex1,vex2;
	printf("请输入无向网中的顶点数和边数:\n");  
	scanf("%d,%d",&G->vexnum,&G->arcnum);  
	for(i=1;i<=G->vexnum;i++){
		for(j=1;j<=G->vexnum;j++){
			G->arcs[i][j]=INFINITY;//如果不是网,则赋值0
		}
	}		
	printf("请输入无向网中%d个顶点:\n",G->vexnum);  
	for(i=1;i<=G->vexnum;i++){
		printf("No.%d个顶点:顶点V:",i);  
		scanf("%d", &G->vex[i]);
	} 
	printf("\n请输入无向网中%d条边:",G->arcnum);  
	for(k=0;k<G->arcnum;k++){
		printf("\nNo.%d条边:\n",k+1);  
		printf("顶点V:"); 
		scanf("%d",&vex1);
		printf ("<--->顶点V:");
		scanf ("%d",&vex2);
		printf("权值:");
		scanf("%d", &weight);
		G->arcs[vex1][vex2] =weight;//如果不是网,则赋值1		
		G->arcs[vex2][vex1] =weight;//如果是有向网,删掉此句
		
	}

	
}
void Printf(AdjMatrix* G){
	printf("共有%d个顶点",G->vexnum);
	printf("共有%d条边",G->arcnum);
	printf("\n");
	 	
	int i,j;
	printf("\\     ");
	for(i=1;i<=G->vexnum;i++){
		printf("%-5d ",G->vex[i]);
	}
	printf("\n");
	for(i=1;i<=G->vexnum;i++){
		printf("%-5d ",G->vex[i]);
		for(j=1;j<=G->vexnum;j++){			
			printf("%-5d ",G->arcs[i][j]);
		}
		printf("\n");
	}
}

void main(){
	AdjMatrix* G=(AdjMatrix*)malloc(sizeof(AdjMatrix));
	Create(G);
	
	Printf(G);
	
} 

运行结果如下
在这里插入图片描述

2-邻接矩阵plus.c

适用于各种类型的图

//邻接矩阵的数据类型描述为:
#include<stdio.h> 
#include<stdlib.h>

#define MAXVEX 20				//最大顶点个数		
#define INFINITY 32768			//表示极大值 
typedef enum GraghType{
	UG=1,DG,UN,DN
}GT; 
typedef int Vextype;  
typedef struct{
	int arcs[MAXVEX][MAXVEX];	//边(或弧)信息
	Vextype vex[MAXVEX];		//顶点信息,顶点类型根据实际情况自行定义
	int vexnum;					//顶点数目
	int arcnum;					//边(或弧)数目
	GT t;
}AdjMatrix;//邻接矩阵
void type(GT t){
	
	switch(t){
		case UG:
			printf("无向图");
			break; 
		case DG:
			printf("有向图");
			break; 
		case UN:
			printf("无向网");
			break; 
		case DN:
			printf("无向网");
			break; 
	}
	
}
//【算法7.1】用邻接矩阵创建无向网
void Create(AdjMatrix *G){
	GT t=G->t;
	int i,j,k,weight,vex1,vex2;
	
	printf("请输入");  
	type(t);
	printf("中的顶点数和边数:\n");
	
	scanf("%d,%d",&G->vexnum,&G->arcnum);  
	for(i=1;i<=G->vexnum;i++){
		for(j=1;j<=G->vexnum;j++){
			G->arcs[i][j]=INFINITY;//如果不是网,则赋值0
		}
	}	
	
	printf("请输入");  
	type(t);	
	printf("中%d个顶点:\n",G->vexnum);  
	
	for(i=1;i<=G->vexnum;i++){
		printf("No.%d个顶点:顶点V:",i);  
		scanf("%d", &G->vex[i]);
	} 
	printf("\n请输入");  
	type(t);
	printf("中%d条边:",G->arcnum);  
	for(k=0;k<G->arcnum;k++){
		printf("\nNo.%d条边:\n",k+1);  
		printf("顶点V:"); 
		scanf("%d",&vex1);
		printf ("<--->顶点V:");
		scanf ("%d",&vex2);
		printf("权值:");
		scanf("%d", &weight);
		if(G->t==1||G->t==2){
			weight=1;
		}
		G->arcs[vex1][vex2] =weight;//如果不是网,则赋值1
		if(G->t==1||G->t==3){
			G->arcs[vex2][vex1] =weight;//如果是有向网,删掉此句
		}		
		
		
	}

	
}
void Printf(AdjMatrix* G){
	printf("图的类型:");
	type(G->t);
	printf("\n");
	printf("共有%d个顶点",G->vexnum);
	printf("共有%d条边",G->arcnum);
	printf("\n");
	 	
	int i,j;
	printf("\\     ");
	for(i=1;i<=G->vexnum;i++){
		printf("%-5d ",G->vex[i]);
	}
	printf("\n");
	for(i=1;i<=G->vexnum;i++){
		printf("%-5d ",G->vex[i]);
		for(j=1;j<=G->vexnum;j++){			
			printf("%-5d ",G->arcs[i][j]);
		}
		printf("\n");
	}
}


void main(){
	printf("创建\n");
	AdjMatrix* G=(AdjMatrix*)malloc(sizeof(AdjMatrix));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 
	Create(G);
	
	printf("打印\n");
	Printf(G);
	
} 

运行结果如下
在这里插入图片描述

7.3.2 邻接表

邻接表由边表和顶点表组成。
边表就是对图中的每一个顶点建立一条单链表,表中存放与该顶点邻接的所有顶点,相当于邻接矩阵的所有非零元素。
顶点表用于存放图中每一个顶点的信息以及指向改顶点边表的头指针。
顶点结构
vexdata head
图的边结构
adjvex next
网的边结构
adjvex weight next

邻接矩阵的数据类型描述为:

#include<stdio.h> 
#include<stdlib.h>
#define MAXVEX 20			
typedef struct ArcNode{
	int adjvex;
	int weight;
	struct ArcNode *next;
}ArcNode;

3-邻接表.c

只针对无向网

//邻接矩阵的数据类型描述为:
#include<stdio.h> 
#include<stdlib.h>
#define MAXVEX 20			
typedef struct ArcNode{
	int adjvex;
	int weight;
	struct ArcNode *next;
}ArcNode;

typedef struct VertexNode{
	char vexdata;	
	ArcNode *head;
}VertexNode;

typedef struct {
	VertexNode vertex[MAXVEX];
	int vexnum;//顶点数 
	int arcnum;//弧数 
}AdjList;

//用邻接表创建无向网
void Create(AdjList *G){
	int i,j,k,weight,vex1,vex2;
	printf("请输入无向网中的顶点数和边数:\n");  
	scanf("%d,%d",&G->vexnum,&G->arcnum);  
					
	printf("请输入无向网中%d个顶点:\n",G->vexnum);  
	for(i=1;i<=G->vexnum;i++){		
		VertexNode v;		
		printf("No.%d个顶点:顶点V:",i);
		char c=getchar();
//		if(c=='\n'){
//			c=getchar();
//		}
		fflush(stdin);  
		scanf("%c",&v.vexdata);
//		v.vexdata=c;
		v.head=(ArcNode*)malloc(sizeof(ArcNode));
		G->vertex[i]=v;
		
	} 
	printf("\n请输入无向网中%d条边:",G->arcnum);  
	for(k=0;k<G->arcnum;k++){
		printf("\nNo.%d条边:\n",k+1);  
		printf("顶点V:"); 
		scanf("%d",&vex1);
		printf ("<--->顶点V:");
		scanf ("%d",&vex2);
		printf("权值:");
		scanf("%d", &weight);
		
		ArcNode *r1;
		r1=G->vertex[vex1].head;
		ArcNode *r2;
		r2=G->vertex[vex2].head;
		
		ArcNode *s1=(ArcNode*)malloc(sizeof(ArcNode));
		ArcNode *s2=(ArcNode*)malloc(sizeof(ArcNode));
		s1->adjvex=vex2;
		s1->weight=weight;//如果不是网,则赋值1	
		r1->next=s1;
		
		s2->adjvex=vex1;
		s2->weight=weight;//如果不是网,则赋值1
		r2->next=s2;
		
		r1=s1;
		r2=s2;
				
		r1->next=NULL;
		r2->next=NULL;
	}
		
	
}
void Printf(AdjList* G){
	printf("共有%d个顶点",G->vexnum);
	printf("共有%d条边",G->arcnum);
	printf("\n");
	 	
	int i,j;
	
	for(i=1;i<=G->vexnum;i++){
		printf("%c(%d) ",G->vertex[i].vexdata,i);
		ArcNode* p=G->vertex[i].head->next;
		while(p!=NULL){
			
			printf("--%d--",p->weight);
			printf("%c(%d)    ",G->vertex[p->adjvex].vexdata,p->adjvex);
			
			p=p->next;			
		}
		
		printf("\n");
	
	}
	
	
}

void main(){
	AdjList* G=(AdjList*)malloc(sizeof(AdjList));
	Create(G);
	
	Printf(G);
	
} 

运行结果如下
在这里插入图片描述

4-邻接表plus.c

适用于各种类型的图

//邻接矩阵的数据类型描述为:
#include<stdio.h> 
#include<stdlib.h>
#define MAXVEX 20	
typedef enum GraghType{
	UG=1,DG,UN,DN
}GT; 		
typedef struct ArcNode{
	int adjvex;
	int weight;
	struct ArcNode *next;
}ArcNode;

typedef struct VertexNode{
	char vexdata;	
	ArcNode *head;
}VertexNode;

typedef struct {
	VertexNode vertex[MAXVEX];
	int vexnum;//顶点数 
	int arcnum;//弧数 
	GT t;
}AdjList;
void type(GT t){
	
	switch(t){
		case UG:
			printf("无向图");
			break; 
		case DG:
			printf("有向图");
			break; 
		case UN:
			printf("无向网");
			break; 
		case DN:
			printf("有向网");
			break; 
	}
	
}
//用邻接表创建无向网
void Create(AdjList *G){
	GT t=G->t;
	int i,j,k,weight,vex1,vex2;
	printf("请输入");  
	type(t);
	printf("中的顶点数和边数:\n");  
	scanf("%d,%d",&G->vexnum,&G->arcnum);  
	
	printf("请输入");  
	type(t);				
	printf("中%d个顶点:\n",G->vexnum);  
	for(i=1;i<=G->vexnum;i++){		
		VertexNode v;		
		printf("No.%d个顶点:顶点V:",i);
//		char c=getchar();
//		if(c=='\n'){
//			c=getchar();
//		}
		fflush(stdin);  
		scanf("%c",&v.vexdata);
//		v.vexdata=c;
		v.head=(ArcNode*)malloc(sizeof(ArcNode));
		v.head->next=NULL;
		G->vertex[i]=v;
		
	} 
	printf("\n请输入");  
	type(t);
	printf("中%d条边:",G->arcnum);  
	
	
	for(k=0;k<G->arcnum;k++){
		printf("\nNo.%d条边:\n",k+1);  
		printf("顶点V:"); 
		scanf("%d",&vex1);
		printf ("<--->顶点V:");
		scanf ("%d",&vex2);
		printf("权值:");
		scanf("%d", &weight);
		if(G->t==1||G->t==2){
			weight=1;//如果不是网,则赋值1	
		}
		
		
		ArcNode *r1= G->vertex[vex1].head;//尾结点 
		while(r1->next!=NULL){
			r1=r1->next;
		}
		
		
		ArcNode *s1=(ArcNode*)malloc(sizeof(ArcNode));		
		s1->adjvex=vex2;
		s1->weight=weight;
		s1->next=r1->next;
		r1->next=s1;
		
//		r1->next=NULL;
		
		if(G->t==1||G->t==3){
			ArcNode *r2= G->vertex[vex2].head;//尾结点 
			while(r2->next!=NULL){
				r2=r2->next;
			}
			
			ArcNode *s2=(ArcNode*)malloc(sizeof(ArcNode));
			s2->adjvex=vex1;
			s2->weight=weight;	
			s2->next=r2->next;
			r2->next=s2;			
								
//			r2->next=NULL;			
		}
		
		
	}
		
	
}
void Printf(AdjList* G){
	printf("图的类型:");
	type(G->t);
	printf("\n");
	printf("共有%d个顶点",G->vexnum);
	printf("共有%d条边",G->arcnum);
	printf("\n");
	 	
	int i,j;
	
	for(i=1;i<=G->vexnum;i++){
		
		ArcNode* p=G->vertex[i].head->next;
		while(p!=NULL){
			printf("%c(%d) ",G->vertex[i].vexdata,i);
			printf("--%d--",p->weight);
			printf("%c(%d)    ",G->vertex[p->adjvex].vexdata,p->adjvex);
			
			p=p->next;			
		}
		
		printf("\n");
	
	}
	
	
}

  
void main(){
	AdjList* G=(AdjList*)malloc(sizeof(AdjList));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 	
	Create(G);
	
	Printf(G);
	
} 

运行结果如下
在这里插入图片描述

7.3.3 十字链表

7.3.4多重链表

7.4图的遍历

7.4.1深度优先搜索遍历

图的深度优先搜索遍历类似于树的先序遍历,尽可能先对纵深方向进行搜索。其基本思想为从图中某个顶点V出发,访问此顶点,然后依次从V的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V,有路径相通的顶点都被访问到。若图是连通图,则遍历过程结束,否则,图中还有顶点未被访问,则另选图中一个未被访问的顶点作
为新的出发点。重复上述过程,直至图中所有顶点都被访问到。

5-DFSAdjMatrix.c
#include<stdio.h>
#include "2-邻接矩阵plus.c" //去掉main()

void visit(int v0){
	printf("%d ",v0);
} 
//【算法 7-2】递归深度优先搜索遍历连通子图
int visited[MAXVEX]={0};//设置标志数组 
//从v0出发递归地深度优先搜索遍历连通子图
void DFSAdjMatrix(AdjMatrix g,int v0){
	visit(v0);
	visited[v0]=1;
	int vj;
	//搜索图 
	if(g.t==1||g.t==2){
		for(vj=1;vj<=g.vexnum;vj++){
			if(visited[vj]==0&&g.arcs[v0][vj]==1) {
				DFSAdjMatrix(g,vj); 
			}
		}
	} 
	
	//搜索网
	if(g.t==3||g.t==4){
		for(vj=1;vj<=g.vexnum;vj++){
			if(visited[vj]==0&&g.arcs[v0][vj]!=INFINITY) {
				DFSAdjMatrix(g,vj); 
			}
		}
	} 
}
//【算法 7-3】深度优先遍历图g 
void TraverseG(AdjMatrix g){
	int v;
	for(v=1;v<=g.vexnum;v++){
		visited[v]=0;
	}
	for(v=1;v<=g.vexnum;v++){
		if(!visited[v]){
			DFSAdjMatrix(g,v);
		}
	}
}
//int HasAPath(AdjMatrix g, int v, int w) {
//	DFSAdjMatrix(g,v);
//    if(visited[w]==1){
//        return 1;
//    }
//	return 0;
//    
//
//}

typedef int ElemType;
#include "顺序栈.h"

int FirstAdjVex(AdjMatrix g,int v){
	int null=INFINITY;
	
	int n=g.vexnum;
	int i=1;
	for(;i<=n;i++){
		if(g.arcs[v][i]!=null){
			break;
		}
	}
	if(i>n){
		return -1;
	} else{
		return i;
	} 
	
	
}
int NextAdjVex(AdjMatrix g,int v,int w){
	int null=INFINITY;
	int n=g.vexnum;
	int i=w+1;
	for(;i<=n;i++){
		if(g.arcs[v][i]!=null){
			break;
		}
	}
	if(i>n){
		return -1;
	} else{
		return i;
	} 
	
}
//【算法 7-4】非递归深度优先搜索遍历连通子图
//从v0出发递归地深度优先搜索遍历连通子图
void DFS(AdjMatrix g,int v0){
	SeqStack *S=InitStack();
	int visited[MAXVEX]={0};//访问标志数组
	Push(S,v0);
	while(!Empty(S)){
		int v;
		Pop(S,&v);
		if(!visited[v]){
			visit(v);
			visited[v]=1;
		}
		int w=FirstAdjVex(g,v);//图g中顶点v的第一个邻接点 
		while(w!=-1){
			if(!visited[w]){
				Push(S,w);
			}
			w=NextAdjVex(g,v,w);//图g中顶点v的下一个邻接点
		}
	} 
} 

void main(){
	printf("创建\n");
	AdjMatrix* G=(AdjMatrix*)malloc(sizeof(AdjMatrix));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 
	Create(G);
	
	
	int v0=1;
	printf("从v0=%d开始DFS:\n",v0); 
	DFSAdjMatrix(*G,v0);
	
	printf("\n");
	printf("DFS:\n"); 
	TraverseG(*G);
	printf("\n"); 
	
//	visited[MAXVEX]={0};
//	int r=HasAPath(*G,1,2); 
//	printf("%d",r);

	printf("非递归DFS:\n");
	DFS(*G,1);
	printf("\n"); 	
	
	printf("打印\n");
	Printf(G);
} 

运行结果如下
在这里插入图片描述
非递归DFS
在这里插入图片描述

6-DFSAdjList.c
#include<stdio.h>
#include "4-邻接表plus.c" //去掉main()
void visit(int v0){
	printf("%d ",v0);
} 

//【算法 7-2】递归深度优先搜索遍历连通子图

int visited[MAXVEX]={0};//设置标志数组 
//从v0出发递归地深度优先搜索遍历连通子图

void DFSAdjList(AdjList g,int v0){
	visit(v0);
	visited[v0]=1;
	
	ArcNode* p=g.vertex[v0].head->next;
	while(p!=NULL){
		if(!visited[p->adjvex]){
			DFSAdjList(g,p->adjvex);			
		}
		p=p->next;
	}
}
//【算法 7-3】深度优先遍历图g 
void TraverseG(AdjList g){
	int v;
	for(v=1;v<=g.vexnum;v++){
		visited[v]=0;
	}
	for(v=1;v<=g.vexnum;v++){
		if(!visited[v]){
			DFSAdjList(g,v);
		}
	}
}


typedef int ElemType;
#include "顺序栈.h"


int FirstAdjVex(AdjList g,int v){
	ArcNode* h=g.vertex[v].head;
	ArcNode* p=h->next;
	if(p==NULL){
		return -1;
	}else{
		return p->adjvex;
	}
	
}
int NextAdjVex(AdjList g,int v,int w){
	ArcNode* h=g.vertex[v].head;
	ArcNode* p=h->next;
	//找到之前的邻接点w 
	while(p){
		if(p->adjvex==w){
			break;
		}
		p=p->next;
	}
	//找到w下一个邻接点
	p=p->next;
	if(p==NULL){
		return -1;
	}else{
		return p->adjvex;
	}	
	
}
//【算法 7-4】非递归深度优先搜索遍历连通子图
//从v0出发递归地深度优先搜索遍历连通子图
void DFS(AdjList g,int v0){
	SeqStack *S=InitStack();
	int visited[MAXVEX]={0};//访问标志数组
	Push(S,v0);
	while(!Empty(S)){
		int v;
		Pop(S,&v);
		if(!visited[v]){
			visit(v);
			visited[v]=1;
		}
		int w=FirstAdjVex(g,v);//图g中顶点v的第一个邻接点 
		while(w!=-1){
			if(!visited[w]){
				Push(S,w);
			}
			w=NextAdjVex(g,v,w);//图g中顶点v的下一个邻接点
		}
	} 
} 


void main(){
	printf("创建\n");
	AdjList* G=(AdjList*)malloc(sizeof(AdjList));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 
	Create(G);
	
	printf("DFS:\n"); 
//	int v0=1;
//	DFSAdjMatrix(*G,v0);
	TraverseG(*G);
	printf("\n"); 
	
	printf("非递归DFS:\n"); 	
	DFS(*G,1); 
	printf("\n"); 	
		
	printf("打印\n");
	Printf(G);
	
} 

运行结果如下
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
非递归DFS测试
在这里插入图片描述

7.4.2广度优先搜索遍历

图的广度优先搜索遍历类似于树的按层次遍历,其基本思想为从图中的某个顶点V0出发,在访问此顶点之后依次访问V0。的所有未被访问的邻接点,之后按这些邻接点被访问的先后次序依次访问它们的邻接点,直至图中所有和V0有路径相通的顶点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未被访问的顶点作为新的出发点,重复上述过程,直至图中所有顶点都被访问到。

7-BFSAdjMatrix.c
#include<stdio.h>
#include "2-邻接矩阵plus.c" //去掉main()
#include "链队列.h" //去掉main()

int visited[MAXVEX]={0};//设置标志数组 
//从v0出发递归地深度优先搜索遍历连通子图
void visit(int v0){
	printf("%d ",v0);
} 
//【算法7-5】广度优先搜索遍历连通子图
void BFSAdjMatrix(AdjMatrix g,int v0){
	int v; 
	visit(v0);
	visited[v0]=1;
	LQueue *Q=Init_LQueue();
	InLQueue(Q,v0);//入队
	int vj; 
	while(!Empty_LQueue(Q)){
		Out_LQueue(Q,&v);//出队
		//搜索图 
		if(g.t==1||g.t==2){
			for(vj=1;vj<=g.vexnum;vj++){
				if(visited[vj]==0&&g.arcs[v][vj]==1) {
					visit(vj);
					visited[vj]=1;
					InLQueue(Q,vj);
				}
			}
		} 
		
		//搜索网
		if(g.t==3||g.t==4){
			for(vj=1;vj<=g.vexnum;vj++){
				if(visited[vj]==0&&g.arcs[v][vj]!=INFINITY) {
					visit(vj);
					visited[vj]=1;
					InLQueue(Q,vj); 
				}
			}
		}  
	} 
	 
	
	
}
//【算法7-6】广度优先遍历图g 
void TraverseG(AdjMatrix g){
	int v;
	for(v=1;v<=g.vexnum;v++){
		visited[v]=0;
	}
	for(v=1;v<=g.vexnum;v++){
		if(!visited[v]){
			BFSAdjMatrix(g,v);
		}
	}
}


void main(){
	printf("创建\n");
	AdjMatrix* G=(AdjMatrix*)malloc(sizeof(AdjMatrix));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 
	Create(G);
	
	printf("BFS:\n"); 
//	int v0=1;
//	BFSAdjMatrix(*G,v0);
	TraverseG(*G);
	printf("\n"); 
	
	printf("打印\n");
	Printf(G);
	
} 

在这里插入图片描述

在这里插入图片描述

8-BFSAdjList.c
#include<stdio.h>
#include "4-邻接表plus.c" 
#include "链队列.h" 

int visited[MAXVEX]={0};//设置标志数组 
//从v0出发递归地深度优先搜索遍历连通子图
void visit(int v0){
	printf("%d ",v0);
} 
//【算法 7-5】广度优先搜索遍历连通子图
void BFSAdjList(AdjList g,int v0){
	visit(v0);
	visited[v0]=1;
	LQueue *Q=Init_LQueue();
	InLQueue(Q,v0);//入队
	int v;
	while(!Empty_LQueue(Q)){
		Out_LQueue(Q,&v);//出队
		ArcNode* p=g.vertex[v].head->next;
		if(!visited[p->adjvex]){
			visit(p->adjvex);
			visited[p->adjvex]=1;
					
		}
		p=p->next;
	}
}
//【算法7-6】广度优先遍历图g 
void TraverseG(AdjList g){
	int v;
	for(v=1;v<=g.vexnum;v++){
		visited[v]=0;
	}
	for(v=1;v<=g.vexnum;v++){
		if(!visited[v]){
			BFSAdjList(g,v);
		}
	}
}


void main(){
	printf("创建\n");
	AdjList* G=(AdjList*)malloc(sizeof(AdjList));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 
	Create(G);
	
	printf("BFS:\n"); 
//	int v0=1;
//	BFSAdjList(*G,v0);
	TraverseG(*G);
	printf("\n"); 
	
	printf("打印\n");
	Printf(G);
	
} 

运行结果如下

在这里插入图片描述

7.5图的应用

7.5.1最小生成树

图G的生成树是指该图的一个极小连通子图,含有图中的全部n个顶点,但只有足以构成
棵树的n-1条边。显然,生成树不唯一,可能有多棵。
在一个连通网的所有生成树中,选中的n-1条边权值(代价)之和最小的生成树被称为该连通网的“最小代价生成树"(minimum-cost spanning tree,MST)。
MST性质:设图G=<V,R>是一个带权的连通图,即连通网,集合U是顶点集V的一个非空
子集。构建生成树时需要一条边连通顶点集合U和V-U。如果(u,v)∈R,其中,u∈U,v∈V-U,且边(u,v)是具有最小权值的一条边,那么一定存在一棵包含边(u,v)的最小生成树。
1.Prim算法(加点法)
适用于稠密图
基本思想:从连通网络N={v,E}中的某一顶点u出发,选择与它关联的具有最小权值的边(u0,v),将其顶点加人生成树的顶点集合U。以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u,v),把它的顶点加人集合U中,这意味着(u,v)也加入生成树的边集合。如此继续下去,直到网络中的所有顶点都加入生成树的顶点集合U中为止。

具体地,记N是连通网的顶点集,U是求得生成树的顶点集,TE是求得生成树的边集
①开始时,U={U0}TE=∅。
②修正U到其余顶点N-U的最小权值,将具有最小权值的边纳入TE,对应的顶点纳入U。
③重复②直到U=N。
经过上述步骤,TE中包含了G中的n-1条边,此时选取到的所有顶点及边恰好就构成了G的一棵最小生成树。

9-Prim.c
#include<stdio.h>
#include "2-邻接矩阵plus.c"
typedef int VertexData;
int LocateVertex(AdjMatrix gn,VertexData u){
	int i;
	for(i=1;i<=gn.vexnum;i++){
		if(gn.vex[i]==u){
			return i;
		}
	}
}

//【7-7】Prim算法求得最小生成树 
void Prim(AdjMatrix gn,VertexData u){
	struct{
		int adjvex;
		int lowcost;
	}closedge[MAXVEX];
	int k;
	k=LocateVertex(gn,u);
	closedge[k].lowcost=0;
	int i;
	for(i=1;i<=gn.vexnum;i++){
		if(i!=k){
			closedge[i].adjvex=u;
			closedge[i].lowcost=gn.arcs[k][i];
			
		}
	}
	int k0,u0,v0,e;
	for(e=1;e<=gn.vexnum-1;e++){
		//选择最小权值的边 
		int m,min=INFINITY;
		for(k=1;k<=gn.vexnum;k++){
			if(closedge[k].lowcost!=0&&closedge[k].lowcost<min){
				m=k;
				min=closedge[k].lowcost;
			}
		} 
//		k0=Minium(closedge);
		k0=m;
		u0=closedge[k0].adjvex;
		v0=gn.vex[k0];
		printf("第%d条边:%d--%d--%d\n ",e,u0,min,v0);
		closedge[k0].lowcost=0;
		for(i=1;i<=gn.vexnum;i++){
			if(gn.arcs[k0][i]<closedge[i].lowcost){
				closedge[i].lowcost=gn.arcs[k0][i];
				closedge[i].adjvex=v0;
			}
		}
	}
}

int main(){
	printf("创建\n");
	AdjMatrix* G=(AdjMatrix*)malloc(sizeof(AdjMatrix));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 
	Create(G);
	
	printf("最小生成树\n");
	VertexData u=1;
	Prim(*G,u);
	
	printf("打印\n");
	Printf(G);
}

运行结果如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

说明

最小生成树
每两个代表生成树一个边的两个顶点
4 7 可以改成7 10也是对的

2.Kruskal算法(加边法)
适用于稀疏图
Kruskal算法使用的贪心准则是,从剩下的边中选择不会产生环路且具最小权值的边加人生成树的边集。
基本思想:先构造一个只含n个顶点的子图SG,然后从权值最小的边
开始,若它的添加不使SG中产生回路,则在SG上加入该边,依次按照权值通增的次序,选择合适的边进行添加,如此重复,直至加完n-1条边为止。

7.5.2 拓扑排序

假设以有向图表示个工程的施工图或程序的数据流图,每个顶点代表一个活动,弧<vi,vj)表示活动必须先于活动j进行。我们将顶点表示活动、弧表示活动间优先关系的有向无“顶点表示活动的网”,简称"AOV-网"(activity on vertex),图中不允许出现回路。

对于一个AOV-网,若存在满足以下性质的一个线性序列,则这个线性序列称为“拓扑序列”。
①网中的所有顶点都在该序列中。
②若顶点i到顶点Vj存在一条路径,则在线性序列中,Vi一定排在Vj之前。
构造拓扑序列的操作称为“拓扑排序”。实际上,拓扑排序就是离散数学中由某个集合上一个偏序得到该集合上的一个全序的操作。

那么,对于一个AOV-网来说,如何求得拓扑序列呢?其方法如下。
①从有向图中选取一个没有前驱的顶点并输出之。
②从有向图中删去该顶点以及所有以它为尾的弧。
③重复上述两步,直至图空(不存在回路),或者图不空但找不到无前驱的顶点为止(存在 回路)。可见,拓扑排序可以检查有向图中是否存在回路。

相关代码请看配套资源

10-拓扑排序.c
#include<stdio.h> 
#include<stdlib.h>
#include "4-邻接表plus.c"
#include "链队列.h"

//【算法7-8】获取图中每个顶点入度值】 
void FindID(AdjList G, int indegree[MAXVEX]) {// 格个顶点的人度值
	int i;
	ArcNode *p;
	for(i=1;i<=G.vexnum;i++){
		indegree[i]=0;  //初始化indegree数组  
	}
	
	for(i=1;i<=G.vexnum;i++){
		p=G.vertex[i].head->next;  
		while(p!=NULL){
			indegree[p->adjvex]++; 
			p=p->next;
		}
	}	
}


//【算法7-9】 拓扑排序
int TopoSort (AdjList G){
	LQueue *Q;/*队列*/
	int indegree[MAXVEX]={0};
	int i, count, k;
	ArcNode *p;
	FindID(G,indegree);
	Q=Init_LQueue();
	for(i=1;i<=G.vexnum;i++){
		if(indegree[i]==0){
			InLQueue(Q,i);
		}
	}	
	count=0;
	while(!Empty_LQueue(Q)){
		Out_LQueue(Q,&i);
		printf("%c ",G.vertex[i].vexdata);  
		count++;
		p=G.vertex[i].head->next;
		while(p!=NULL){
			k=p->adjvex;
			indegree[k]--;
			if(indegree[k]==0) {
				InLQueue(Q,k);  
			}
			
			p=p->next;
		}
	
	}
	
	if (count<G.vexnum) return 0;
	else return 1;

}


void main(){
	AdjList* G=(AdjList*)malloc(sizeof(AdjList));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 	
	Create(G);
	printf("\n");	
	
	printf("拓扑排序");
//	int indegree[MAXVEX];
//	FindID(*G,indegree);
//	int i;
//	for(i=1;i<=G->vexnum;i++){
//		printf("%d ",indegree[i]);
//	}
	
	TopoSort(*G);
	printf("\n");
	
	Printf(G);
}

运行结果如下
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.5.3关键路径

7.5.4最短路径

1.单元最短路径
DIjkstra算法

11-单源最短路径.c
#include<stdio.h> 
#include<stdlib.h>
#include "2-邻接矩阵plus.c" 
//【算法7-11】采用Dijkstra算法求得从源点到其余各顶点的最短路径
void Dijkstra(AdjMatrix *G,int start,int end,int dist[],int path[][MAXVEX]){
	//dist数组记录各条最短路径长度,path数组记录对应路径上的各顶点	
	
	int mindist,i,j,k,t=1;
	for(i=1;i<=G->vexnum;i++){	 //初始化
		dist[i]=G->arcs[start][i];
		if(G->arcs[start][i]!=INFINITY){	 
			path[i][1]=start;
		} 
	} 
	path[start][0]=1;
	
	for(i=2;i<=G->vexnum;i++){ //寻找各条最短路径
		mindist=INFINITY;
		
		for(j=1;j<=G->vexnum;j++) { //选择最小权值的路径  
		 	if(!path[j][0]&&dist[j]<mindist){ 		
				k=j;
				mindist=dist[j];
			}
		}	
		if(mindist==INFINITY) return;
		path[k][0]=1;
		for(j=1;j<=G->vexnum;j++){ //修改路径			
			if(!path[j][0]&&G->arcs[k][j]<INFINITY&&dist[k]+ G->arcs[k][j]<dist[j]){
				dist[j]=dist[k]+G->arcs[k][j];
				t=1;
				while(path[k][t]!=0){  //记录最新的最短路径 
					path[j][t]=path[k][t];//伪代码 
					t++;
				} 			
				path[j][t]=k;
				path[j][t+1]=0;
			} 
		}
		
	}
 
}
void printPath(AdjMatrix *G,int start,int end,int dist[],int path[][MAXVEX]){
	int i,j;
	printf("从%d到其余顶点\n",start);
	for(i=1;i<=G->vexnum;i++){	
		if(i==start){
			printf("到本身顶点%d的最短路径长度为0\n",i);
			
		}else{
//			if(path[i][0]==1){
				printf("到顶点%d的最短路径长度为%d\n",i,dist[i]);
				printf("其路径为:"); 
				j=1;
				while(path[i][j]!=0) {
					printf("%d ",path[i][j]);
					j++;
				}
				printf("\n");
//			}else{
//				printf("无路径\n");
//			}
			
		}	
		
	}
}
void main(){
	printf("创建\n");
	AdjMatrix* G=(AdjMatrix*)malloc(sizeof(AdjMatrix));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 
	Create(G);
	printf("\n");
	
	int start=1;
	int end=2;
	int dist[G->vexnum+1];
	int path[G->vexnum+1][MAXVEX];
	Dijkstra(G,start,end,dist,path);	
	printPath(G,start,end,dist,path);
	
	printf("打印\n");
	Printf(G);
} 

运行结果
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.每对顶点之间的路径
Floyd算法

12-多源最短路径.c
#include<stdio.h> 
#include<stdlib.h>
#include "2-邻接矩阵plus.c" 


void printFP(int n,int F[][MAXVEX],int Path[MAXVEX][MAXVEX]){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j){
				printf("0\t");
			}else{
				printf("%d\t",F[i][j]);
			}
		}
		printf("\n");
	}
//	for (int i = 1; i <= n; i++) {
//        for (int j = 1; j <= n; j++) {
//        	printf("%d\t",Path[i][j]);
//        }
//        printf("\n");
//    }
}

//【算法7-12】Floyd算法求得任意两顶点之间的最短路径
void Floyd(AdjMatrix g,int F[][MAXVEX],int Path[][MAXVEX]){

		 
	int i,j,k;
	for(i=1;i<=g.vexnum;i++){
		for(j=1;j<=g.vexnum;j++) {
			F[i][j]=g.arcs[i][j];
//            if (F[i][j] != INFINITY) {
//                Path[i][j] = j; // 如果i和j之间有边,则Path[i][j]为j
//            } else {
//                Path[i][j] = -1; // 如果i和j之间没有边,则Path[i][j]为-1
//            }
		}
	} 

	
	for(i=1;i<=g.vexnum;i++){ 
		for(j=1;j<=g.vexnum;j++) { 
			for(k=1;k<=g.vexnum;k++){ 
				if(F[i][j]>F[i][k]+F[k][j]){
					F[i][j]=F[i][k]+F[k][j];
//					Path[i][j] = Path[i][k]; // 更新Path[i][j]为经过顶点k的路径
				}
			}
		}
	}
 
}

//void printPath(int i, int j, int Path[][MAXVEX]) {
//    if (Path[i][j] == -1) {
//        printf("%d ", i);
//    } else {
//        printPath(i, Path[i][j], Path);
//        printf("%d ", j);
//    }
//}



void main(){
	printf("创建\n");
	AdjMatrix* G=(AdjMatrix*)malloc(sizeof(AdjMatrix));
	printf("输入图的类型 ");
	printf("无向图(1) ");
	printf("有向图(2) ");
	printf("无向网(3) ");
	printf("有向网(4) :");
	scanf("%d",&G->t); 
	Create(G);
	printf("\n");


	printf("打印\n");
	Printf(G);
	
	
	printf("多源最短路径\n");	
	int n=G->vexnum;
	int F[n][n];
	int Path[n][n];
	Floyd(*G,F,Path);
	printFP(n,F,Path);
	
	
//    for (int i = 1; i <= n; i++) {
//        for (int j = 1; j <= n; j++) {
//            if (i != j) {
//                printf("从顶点 %d 到顶点 %d 的最短路径为:", i, j);
//                printPath(i, j, Path);
//                printf("\n");
//            }
//        }
//    }
} 

运行结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

6实例分析与实现

7算法总结 贪心算法

习题7

3完成题 1 2 4 6

(1)对于图7-37所示的有向网:
①给出该图对应的邻接矩阵、邻接表和逆邻接表
②判断该图是否为强连通图,并给出其强连通分量
③给出每个顶点的度、人度和出度
④给出从顶点V,开始的深度优先搜索遍历序列和广度优先搜索遍历序列
请添加图片描述


(2)如图7-38所示的无向网,请给出分别按Prim(从顶点V1开始)和Kruskal算法构造的最小生成树并给出构造过程。
请添加图片描述


(4)如图7-40所示的有向网,利用Dijkstra算法求顶点V0到其他各顶点之间的最短路径以及最短路径长度
请添加图片描述


(6)对如图7-42所示的有向图进行拓扑排序,写出可能的3种拓扑序列。
请添加图片描述

4.算法设计题

(11)已知有向图以邻接表作为存储结构,编写算法判断该图中是否存在顶点Vi到顶点Vj,的简单路径,并输出该路径上的顶点。

最后

2023-11-6 17:51:52

2023-11-7 16:00:47
我们都有光明的未来
不必感谢我,也不必记得我

祝大家考研上岸
祝大家工作顺利
祝大家得偿所愿
祝大家如愿以偿
点赞收藏关注哦

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1180924.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每天一点python——day62

为了方便复制&#xff0c;我在下面附带了一个python文件。 C:\Users\Admin>python Python 3.9.13 (main, Aug 25 2022, 23:51:50) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32Warning: This Python interpreter is in a conda environment, but the environmen…

【蓝桥杯选拔赛真题13】C++最短距离 青少年组蓝桥杯C++选拔赛真题 STEMA比赛真题解析

C/C++最短距离 第十二届青少组蓝桥杯C++选拔赛真题 一、题目要求 1、编程实现 有一个居民小区的楼房全是一样的,并且按矩阵样式排列。其楼房的编号为 1,2,3……,当排满一行时,从下一行相邻的楼往反方向排号。 例如:小区为 3 行 6 列,矩阵排列方式: 要求:已知小区…

python 之列表的常用方法

文章目录 1. **append()** 方法2. **extend()** 方法3. **insert()** 方法4. **pop()** 方法5. **remove()** 方法6. **clear()** 方法7. **index()** 方法8. **count()** 方法9. **reverse()** 方法10. **sort()** 方法 当操作 Python 列表时&#xff0c;常用的方法如下。以下…

Python学习笔记--模块简介

一、Python 模块简介 在开发过程中&#xff0c;随着程序代码越写越多&#xff0c;在一个文件里代码就会越来越长&#xff0c;越来越不容易维护。 后面我们学习了函数&#xff0c;知道函数是实现一项或多项功能的一段程序&#xff0c;这样就更方便我们重复使用代码。 紧接着&…

解析半导体测试系统及半导体的测试方法步骤

半导体如今在集成电路、通信系统、照明等领域被广泛应用&#xff0c;是一种非常重要的材料。在半导体行业中&#xff0c;半导体测试是特别关键的环节&#xff0c;以保证半导体器件及产品符合规定和设计要求&#xff0c;确保其质量和性能。 随着现代电子技术的发展&#xff0c;半…

移远EC600U-CN开发板 day02

1.QuecPythonLVGL显示图片 由于官方提供的显示图片函数使用失败&#xff0c;为了能在屏幕上显示图片&#xff0c;通过对出厂脚本的分析&#xff0c;成功使用LVGL显示图片 (1)代码 import lvgl as lv from tp import gt9xx from machine import LCD from machine import Pin …

别让噪声偷走你的听力

欢声笑语&#xff0c;音乐悠扬&#xff0c;燕语莺声&#xff0c;流水潺潺&#xff0c;和亲友畅所欲言…… 这些愉悦的声音让我们每天的生活更充实&#xff0c;他们也是美好记忆的重要组成部分。听力对于我们的身体健康、情感幸福和整体生活质量起着巨大的作用。 因此保护听力健…

华为fusionInsigtht集群es连接工具

华为fusionInsight为用户提供海量数据的管理及分析功能&#xff0c;快速从结构化和非结构化的海量数据中挖掘您所需要的价值数据。开源组件结构复杂&#xff0c;安装、配置、管理过程费时费力&#xff0c;使用华为FusionInsight Manager将为您提供企业级的集群的统一管理平台,在…

大数据管理平台有什么用?如何利用大数据管理平台优化企业运营?

在数字化时代&#xff0c;大数据管理平台已经成为了企业和组织不可或缺的工具。它不仅可以帮助企业跟踪和解决报修问题&#xff0c;还为数据分析提供了丰富的信息。通过合理利用大数据管理平台进行数据分析&#xff0c;企业可以更好地了解其运营情况&#xff0c;优化设备维修和…

攻防世界题目练习——Web引导模式(四)(持续更新)

题目目录 1. shrine2. very_easy_sql 1. shrine 打开网页题目内容如下&#xff1a; 是一段代码&#xff0c;我们把它还原一下&#xff1a; import flask import osapp flask.Flask(__name__) app.config[FLAG] os.environ.pop(FLAG) #这里应该是将config配置里的FLAG字段设…

Time series analysis of InSAR data: Methods and trends(NASA,2015)

文章目录 ISPRS J PHOTOGRAMMIntroductionPhase unwrapping相位解缠算法综述 Time series analysis of InSAR dataPersistent Scatterer Interferometry (PSI)--持久散射体☆☆☆☆PSInSAR && SBAS-InSAR☆☆☆☆PS-InSARSBAS-InSARDS-InSAR&#xff08;分布式散射体干…

金秋云创季——ECS爆品省钱攻略

阿里云双十一推出优惠活动——“金秋云创季”&#xff0c;其中&#xff0c;云服务ECS下的经济型e实例&#xff0c;低至99元/1年&#xff0c;新老用户都可购买&#xff0c;续费不涨价&#xff1b;轻量应用服务器&#xff0c;2核2G 低至87元1年……官方满减优惠享受折上折。惊喜不…

微服务架构——笔记(4)

微服务架构——笔记&#xff08;4&#xff09; 基于分布式的微服务架构 本次笔记为 此次项目的记录&#xff0c;便于整理思路&#xff0c;仅供参考&#xff0c;笔者也将会让程序更加完善 内容包括&#xff1a;8001集群构建&#xff0c;负载均衡&#xff0c;服务发现&#xff0…

day51

前端框架Booststrap 该框架已经帮我们写了很多页面样式&#xff0c;如果需要使用&#xff0c;只需要下载对应文件直接cv即可 在使用Booststrap的时候&#xff0c;所有发页面样式只需要通过修改class属性来调节即可 什么是Booststrap Bootstrap是一个开源的前端框架&#xff…

基于junit4搭建自定义的接口自动化测试框架

随着业务的逐步稳定&#xff0c;对于接口的改动也会逐渐变少。更多的是对业务逻辑的优化&#xff0c;功能实现的完善。对于测试来说&#xff0c;重复繁琐的功能测试不仅效率低下&#xff0c;而且耗费一定的人力资源。笔者支持的信息流业务下的一个图文管理平台就是一个功能较为…

Elasticsearch:ES|QL 的限制

尽管 ES|QL 带来性能及使用上的便捷&#xff0c;在实际的使用中&#xff0c;它还是有一些限制。在今天的文章中&#xff0c;我们来列举它的一些限制。 结果集大小限制 默认情况下&#xff0c;ES|QL 查询最多返回 500 行。 你可以使用 LIMIT 命令将行数增加到最多 10,000 行。 …

SDH设备

文章目录 实际的SDH设备结构&#xff1a;OSN3500

Archicad 26 (BIM建模软件)

Archicad 26是一款建筑信息模型&#xff08;BIM&#xff09;软件&#xff0c;由Graphisoft公司开发。它提供了全面的设计和建模工具&#xff0c;用于创建3D建筑模型、制作施工图纸等。 Archicad 26支持多种文件格式&#xff0c;并且可以与其他CAD软件进行互操作。它具有强大的建…

关于mysql自增列起始值与数据实际id不一致的问题

从一个数据表生成表结构和数据的脚本之后。把脚本复制到另一个数据库执行同步数据结构和数据。 Navicat 发生了如下异常提示&#xff0c;并中断了脚本执行&#xff1a; Duplicate entry 51110 for key sys_log.PRIMARY 然后检查sys_log表的建表脚本&#xff0c;发现有如下行&…

期中考试后,老师用它发成绩

期中考试过后&#xff0c;对于老师们来说&#xff0c;最烦的就是学生家长一直不停的咨询成绩。然而&#xff0c;一群班群直接公布成绩不仅耗时&#xff0c;还不合规。那么&#xff0c;如何用代码和Excel实现让学生自助查询成绩呢&#xff1f;下面&#xff0c;我将向各位老师介绍…