数据结构(超详细讲解!!)第二十六节 图(中)

news2024/11/27 2:19:58

1.存储结构

1.邻接矩阵

图的邻接矩阵表示法(Adjacency Matrix)也称作数组表示法。它采用两个数组来表示图:

一个是用于存储顶点信息的一维数组;另一个是用于存储图中顶点之间关联关系的二维数组,这个关联关系数组被称为邻接矩阵。        

若图G是一个具有n个顶点的无权图,G的邻接矩阵是具有如下性质的n×n矩阵A:

网的邻接矩阵可定义为:

#define MaxVertexNum 100       /*最大顶点数设为100*/
typedef char VertexType;           /*顶点类型设为字符型*/
typedef int EdgeType;                 /*边的权值设为整型*/
typedef struct 
{	VertexType vexs[MaxVertexNum]; /*顶点表*/
	EdgeType edges[MaxVertexNum][MaxVertexNum];  /*邻接矩阵,即边表*/
    int n,e;                       /*顶点数和边数*/
}MGraph;                              /*Maragh是以邻接矩阵存储的图类型*/

邻接矩阵法的特点

1、存储空间:

对于无向图而言, 它的邻接矩阵是对称矩阵(因为若(vi,vj)∈E(G),则(vj,vi)∈E(G))

因此我们可以采用特殊矩阵的压缩存储法,即只存储其下三角即可,这样,一个具有n个顶点的无向图G它的邻接矩阵需要n(n-1)/2个存储空间。

但对于有向图而言,其中的弧是有方向的, 即若<vi,vj>∈E(G),不一定有<vj,vi>∈E(G),因此有向图的邻接矩阵不一定是对称矩阵,对于有向图的邻接矩阵的存储则需要n2个存储空间。

邻接矩阵的存储空间只和顶点个数有关,和边数无关

2、便于运算:

采用邻接矩阵表示法,邻接矩阵表示法适合于以顶点为主的运算。便于判定图中任意两个顶点之间是否有边相连,即根据A[i,j]=0或1来判断。另外还便于求得各个顶点的度。

对于无向图而言,其邻接矩阵第i行元素之和就是图中第i个顶点的度:

对于有向图而言,其邻接矩阵第i行元素之和就是图中第i个顶点的出度:

对于有向图而言,其邻接矩阵第i列元素之和就是图中第i个顶点的入度:

void CreateMGraph(MGraph *G)
{  int i, j, k;    printf("请输入顶点数和边数(输入格式为:顶点数,边数):\n");
    scanf("%d,%d",&(G->n),&(G->e));          /*输入顶点数和边数*/
    printf(“请输入顶点信息(输入格式为: <回车>顶点号):\n");
    for (i=0;i<G->n;i++)  scanf("\n%c", &(G->vexs[i]));       /*输入顶点信息,建立顶点表*/
    for (i=0;i<G->n;i++)
	for (j=0;j<G->n;j++)  
	         G->edges[i][j]=0;               /*初始化邻接矩阵*/
    printf("请输入每条边对应的两个顶点的序号(输入格式为:i,j):\n");
    for (k=0;k<G->e;k++)
    {	scanf("%d,%d",&i,&j);   /*输入e条边,建立邻接矩阵*/
	G->edges[i][j]=1;        
                 /*若此处加入G->edges[j][i]=1;,则为无向图的邻接矩阵存储建立*/
    }
}

2.邻接表

图的邻接表的存储结构是一种顺序分配和链式分配相结合的存储结构,包括两个部分,一部分是数组,一部分是链表图的链式存储结构。          

1)以一个数组来存储图中所有的顶点信息,数组中每个元素表示图中一个顶点,在邻接表中又称作表头结点,表头结点的结构,vertex域用来存储顶点自身的信息,firstedge域是一个指针,指向一个链表(即与该顶点相关的边链表)。

 对于无向图,第i个链表将图中与顶点νi相邻接的所有顶点链接起来,也就是链表中的每个结点表示了与顶点νi相关的边。

对于有向图的第i个链表有两种构造方式,一种是链接以顶点νi 为尾的所有结点;另外也可以链接以顶点νi 为头的所有结点。为了区别,以后者构造邻接表被称之为有向图的逆邻接表。

核心思想:对具有n个顶点的图建立n个线性链表存储该图

n个头结点之间为一数组结构

1.每一个链表前面设置一个头结点,用来存放一个顶点的数据信息,称之为顶点结点。其构造为

其中,vertex域存放某个顶点的数据信息;  firstedge域指向链表中第一个顶点(即与顶点vi邻接的第一个邻接点)。

2.第i个链表中的每一个链结点(称之为表结点)表示以第i个顶点为出发点的一条边;边结点的构造为

其中,链表中的每个结点在邻接表中又称为表结点,具有相同的结构。adjvex域称为顶点域,它存储了与顶点νi相邻接的顶点在顶点数组中的序号;next域称为链域,存储一个指针,它链接了与顶点νi相邻接的顶点的表结点;info是信息域,可以存储与边相关的一些信息,例如对于带权图可以存储边的权值。

typedef struct node		/*表结点*/
{   int adjvex;                     	/*邻接点域*/
    struct node  * next;      /*指向下一个邻接点的指针域*/
      /*  int info;                若要表示边上信息,则应增加一个数据域info*/
}EdgeNode;       
typedef struct vnode 	      	/*表头结点*/
{   VertexType vertex;           	/*顶点域*/
    EdgeNode  * firstedge;      	/*边表头指针*/
}VertexNode;   
typedef struct
{	VertexNode adjlist[MaxVertexNum];     /*邻接表*/
	int n, e;                             		           /*顶点数和边数*/
}ALGraph;      		/*ALGraph是以邻接表方式存储的图类型*/

邻接表与邻接矩阵比较:

若无向图有n个顶点、e条边,则它的邻接表需要n个头结点和2e个表结点

若有向图有n个顶点、e条边,则它的邻接表需要n个头结点和e个表结点

而邻接矩阵需要n方个数组单元

所以如果边比较少,邻接表更节省空间

联系:邻接表中每个链表对应于邻接矩阵中的一行,链表中结点个数等于一行中非零元素的个数。 区别:

① 对任一确定的无向图,邻接矩阵是唯一的(行列号与顶点编号一致),但邻接表不唯一(链接次序与顶点编号无关)。

② 邻接矩阵的空间复杂度为O(n2),而邻接表的空间复杂度为O(n+e)/O(n+2e)。

用途:邻接矩阵多用于稠密图的存储(e接近n(n-1)/2);而邻接表多用于稀疏图的存储(e<<n2)。

void CreateALGraph(ALGraph *G)
{   int i,j,k;	    EdgeNode * s;
    printf("请输入顶点数和边数(输入格式为:顶点数,边数):\n");
    scanf("%d, %d", &(G->n), &(G->e));   /*读入顶点数和边数*/
    printf(“\n请输入顶点信息(输入格式为: <回车>顶点号):\n");
    for (i = 0; i < G->n; i++)                 	/*建立有n个顶点的顶点表*/
    {        scanf(“\n%c", &(G->adjlist[i].vertex));   	/*读入顶点信息*/
               G->adjlist[i].firstedge = NULL;   /*顶点的边表头指针设为空*/
      }
 printf(“\n请输入边的信息(输入格式为:i,j):\n");
    for (k=0; k<G->e; k++)                     /*建立边表*/
    {       scanf("%d, %d", &i, &j); /*读入边<Vi,Vj>的顶点对应序号*/
            s = (EdgeNode*)malloc(sizeof(EdgeNode));  
                    				/*生成新边表结点s*/
            s->adjvex = j;                        	/*邻接点序号为j*/
           s->next = G->adjlist[i].firstedge;
		/*将新边表结点s用头插法插入到顶点Vi 的边表头部*/ 
           G->adjlist[i].firstedge = s;
    }
}

typedef struct node		/*表结点*/
{   int adjvex;                     	/*邻接点域*/
    struct node  * next;      /*指向下一个邻接点的指针域*/
      /*  int info;                若要表示边上信息,则应增加一个数据域info*/
}EdgeNode;       
typedef struct vnode 	      	/*表头结点*/
{   VertexType vertex;           	/*顶点域*/
    EdgeNode  * firstedge;      	/*边表头指针*/
}VertexNode;   
typedef struct
{	VertexNode adjlist[MaxVertexNum];     /*邻接表*/
	int n, e;                             		           /*顶点数和边数*/
}ALGraph;      		/*ALGraph是以邻接表方式存储的图类型*/

无向图的度        

在无向图的邻接表中,顶点vi的度恰好就是第i个边链表上结点的个数。

有向图的度        

在有向图中,第i个边链表上顶点的个数是顶点vi的出度,只需通过表头向量表中找到第i个顶点的边链表的头指针,实现顺链查找即可。        

求得第i个顶点的入度,也必须遍历整个邻接表,在所有边链表中查找邻接点域的值为i的结点并计数求和。由此可见, 对于用邻接表方式存储的有向图,求顶点的入度并不方便, 它需要通过扫描整个邻接表才能得到结果。

一种解决的方法是逆邻接表法,我们可以对每一顶点vi再建立一个逆邻接表,即对每个顶点vi建立一个所有以顶点vi为弧头的弧的表,如图所示。

在有向图的邻接表中,第 i 个链表中结点的个数是顶点Vi的出度。

在有向图的逆邻接表中,第 i 个链表中结点的个数是顶点Vi 的入度。

带权有向图:

3.十字链表      

十字链表Orthogonal List)是有向图的另一种链式存储结构。 我们也可以把它看成是将有向图的邻接表和逆邻接表结合起来形成的一种链表。 有向图中的每一条弧对应十字链表中的一个弧结点, 同时有向图中的每个顶点在十字链表中对应有一个结点, 叫做顶点结点。这两类结点结构如图所示。

#define  MAX-VERTEX-NUM   10               /*最多顶点个数*/
typedef  enum{DG,  DN,  UDG,  UDN}  GraphKind;    /*图的种类*/ 
    typedef  struct  ArcNode {
       int    tailvex,   headvex;   
       struct  ArcNode  *hlink,   *tlink;      
 } ArcNode; 
 typedef struct VertexNode{
     VertexData   data;      /*顶点信息*/
     ArcNode    *firstin,   *firstout;     
 }VertexNode; 
  typedef struct{
      VertexNode   vertex[MAX-VERTEX-NUM];     
       int   vexnum,   arcnum;     /*图的顶点数和弧数*/ 
       GraphKind   kind;                 /*图的种类*/
 } OrthList;         /*图的十字链表表示法(Orthogonal List)*/ 

//建立十字链表
void  CrtOrthList(OrthList g)
/*从终端输入n个顶点的信息和e条弧的信息, 以建立一个有向图的十字链表*/
{
  scanf(″%d, %d″, &n, &e);  /*从键盘输入图的顶点个数和弧的个数*/ 
  for (i=0; i<n; i++) 
     {scanf(″%c″, g.vertex[i].data); 
       g.vertex[i] .firstin=NULL; g.vertex[i] .firstout=NULL; 
     } 
 for (k=0; k<e; k++) 
    {scanf(″%c, %c″, &vt, &vh); 
      i=LocateVertex(g, vt); j = LocateVertex(g,vh); 
      p=alloc(sizeof(ArcNode)); 
      p->tailvex=i; p->headvex=j; 
      p->tlink = g.vertex[i].firstout; g.vertex[i].firstout =p; 
      p->hlink = g.vertex[j].firstin; g.vertex[j].firstin =p; 
    }
 }/* CrtOrthList */ 

4.邻接多重表

邻接多重表(Adjacency Multi-list)是无向图的另外一种存储结构, 之所以提出邻接多重表这种存储结构是因为它能够提供更为方便的边处理信息。 在无向图的邻接表表示法中, 每一条边(vi, vj)在邻接表中都对应着两个结点, 它们分别在第i个边链表i和第j个边链表中。 这给图的某些边操作带来不便, 如检测某条边是否被访问过, 则需要同时找到表示该条边的两个结点, 而这两个结点又分别在两个边链表中。 邻接多重表是指将图中关于一条边的信息用一个结 点来表示, 图中的每一个顶点也对应一个顶点结点。

typedef  struct  EdgeNode { 
      int  mark, ivex, jvex; 
      struct  EdgeNode  *ilink,   *jlink; 
}EdgeNode; 
typedef struct { 
      VertexData  data;  
      EdgeNode  *firstedge; 
}VertexNode; 
typedef struct{
      VertexNode  vertex[MAX-VERTEX-NUM];     
       int   vexnum,   arcnum;              /*图的顶点数和弧数*/ 
       GraphKind   kind;                        /*图的种类*/
} AdjMultiList;          /*基于图的邻接多重表表示法(Adjacency Multi-list)*/ 

2.图的遍历

图的遍历(Travelling Graph):从图中某一个顶点出发,访问图中的其余顶点,使每个顶点被访问一次且仅被访问一次。

方法: 深度优先搜索,广度优先搜索

设访问标志数组visited[]:用于标示图中每个顶点是否被访问过,它的初始值为0(“假”),表示顶点均未被访问;一旦访问过顶点vi,则置访问标志数组中的visited[i]为1(“真”),以表示该顶点已访问。

1.深度优先搜索        

深度优先搜索(Depth-First Search)是指按照深度方向搜索,它类似于树的先根遍历,是树的先根遍历的推广。        

深度优先搜索连通子图的基本思想是:      

(1) 从图中某个顶点v0出发,首先访问v0。      

(2)找出刚访问过的顶点vi的第一个未被访问的邻接点, 然后访问该顶点。以该顶点为新顶点,重复本步骤,直到当前的顶点没有未被访问的邻接点为止。      

(3)返回前一个访问过的且仍有未被访问的邻接点的顶点, 找出并访问该顶点的下一个未被访问的邻接点,然后执行步骤(2)。

采用递归的形式说明,则深度优先搜索连通子图的基本思想可表示为:    

(1) 访问出发点v0。      

(2)依次以v0的未被访问的邻接点为出发点, 深度优先搜索图, 直至图中所有与v0有路径相通的顶点都被访问。        

若此时图中还有顶点未被访问,则另选图中一个未被访问的顶点作为起始点,重复上述深度优先搜索过程,直至图中所有顶点均被访问过为止。        

void DFSTraverseAL(ALGraph *G)	/*算法6-3 */
{	int i;
	for (i=0; i<G->n; i++)
		visited[i] = FALSE;    /*标志向量初始化*/
	for (i=0; i<G->n; i++) 	/*vi未访问过,从vi开始DFS搜索*/
		if (!visited[i]) DFSAL(G, i);          		
}
void DFSAL(ALGraph *G, int i)		/*算法6-4*/
{	EdgeNode *p;
	printf("visit vertex:V%c\n", G->adjlist[i].vertex);  /*访问顶点vi*/
	visited[i]=TRUE;                     /*标记vi已访问*/
	p=G->adjlist[i].firstedge;       /*取vi边表的头指针*/
	while(p)                            	  /*依次搜索vi的邻接点vj */
	{	if (!visited[p->adjvex])    
			/*若vj尚未访问,则以vj为出发点向纵深搜索*/
	       		DFSAL(G,p->adjvex);
	    	p=p->next;                 /*找vi的下一个邻接点/
	}
}

设无向图G有n个顶点、e条边,由于对邻接表中的每个顶点最多检测一次,共有2e个表结点,故完成搜索的时间复杂度为O(n+e)。

2.广度优先搜索

 广度优先搜索(Breadth-First Search)是指照广度方向搜索,它类似于树的层次遍历,是树的按层次遍历的推广。广度优先搜索的基本思想是:    

(1) 从图中某个顶点v0出发,首先访问v0 。    

(2) 依次访问v0的各个未被访问的邻接点。    

(3)分别从这些邻接点(端结点)出发,依次访问它们的各个未被访问的邻接点(新的端结点)。访问时应保证:如果vi和vk为当前端结点,vi在vk之前被访问, 则vi的所有未被访问的邻接点应在vk的所有未被访问的邻接点之前访问。重复(3), 直到所有端结点均没有未被访问的邻接点为止。 

广度优先遍历——仿树的层次遍历过程

访问顶点v

依次访问顶点v的各个未被访问的邻接点

分别从这些邻接点出发,依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于”后被访问的顶点的邻接点”被访问

若此时图中尚有顶点未被访问,则任选其一为起点,重复,直至图中所有顶点都被访问到

注意对比树的层序遍历

广度优先搜索在搜索访问一层时,需要记住已被访问的顶点,以便在访问下层顶点时,从已被访问的顶点出发搜索访问其邻接点。所以在广度优先搜索中需要设置一个队列Queue,使已被访问的顶点顺序由队尾进入队列。在搜索访问下层顶点时,先从队首取出一个已被访问的上层顶点,再从该顶点出发搜索访问它的各个邻接点。

void BFSTraverseAL(MGraph *G)
{	int i;
    	for (i=0; i<G->n; i++)
       		visited[i] = FALSE;            /*标志向量初始化*/
    	for (i=0; i<G->n; i++)
		if (!visited[i]) 	     /* vi未访问过,从vi开始BFS搜索*/
			BFSM(G, i);
}
void BFSM(MGraph *G,int k)
{   int i, j;     CirQueue *Q;       InitQueue(Q);
    printf("visit vertex:V%c\n", G->vexs[k]);               /*访问原点vk*/
    visited[k] = TRUE;       EnQueue(Q, k);                   /*原点vk入队列*/
    while (!QueueEmpty(Q))
    {	i = DeQueue(Q);                      	/*vi出队列*/
              for (j=0; j<G->n; j++)                   	/*依次搜索vi的邻接点vj*/
	        if (G->edges[i][j]==1 && !visited[j]) 		/*若vj未访问*/
	        {	printf("visit vertex:V%c\n", G->vexs[j]); 	/*访问vj */
            	   	visited[j] = TRUE;
   	        	EnQueue(Q, j);            	/*访问过的vj入队列*/
        	         }
    }
}

算法的时间复杂度为O(n2)。如果采用邻接表作为存储结构,所需时间复杂度为O(n+e)。

例题:

求距离顶点v0的路径长度为k的所有顶点。 已知无向图g, 设计算法求距离顶点v0的最短路径长度为K的所有顶点, 要求尽可能节省时间。 

void bfsKLevel(Graph  g,  int  v0,  int  K)
{ InitQueue(Q1); 	 /* Q1是存放已访问顶点的队列*/ 
   InitQueue(Q2);              /* Q2是存放已访问顶点层号的队列 */ 
  for (i=0; i < g .vexnum; i++)  
         visited[i]=FALSE;         /* 初始化访问标志数组 */
  visited[v0]=TRUE;  Level=1; 
  EnterQueue(Q1, v0); 
  EnterQueue(Q2, Level); 
  while (! IsEmpty(Q1) && Level<K+1)
 {
  v=DeleteQueue(Q1);           /* 取出已访问的顶点号 */ 
  Level=DeleteQueue(Q2);       /* 取出已访问顶点的层号 */  
 w=FirstAdjVertex(g, v);         /* 找第一个邻接点 */
  while (w!=-1) 
   {   
    if (! visited[w])  
     {     
      if  (Level==K)  printf(″%d″, w);    /* 输出符合条件的结点 */   
      visited[w]=TRUE;     
      EnterQueue(Q1,  w);     
      EnterQueue(Q2,  Level+1);      
                  }  
     w=NextAdjVertex(g, v, w);         /* 找下一个邻接点 */  
    }
   }
  } 

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

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

相关文章

基于ROPNet项目训练modelnet40数据集进行3d点云的配置

项目地址&#xff1a; https://github.com/zhulf0804/ROPNet 在 MVP Registration Challenge (ICCV Workshop 2021)&#xff08;ICCV Workshop 2021&#xff09;中获得了第二名。项目可以在win10环境下运行。 论文地址&#xff1a; https://arxiv.org/abs/2107.02583 网络简介…

vue2项目中添加字体文件

vue2项目中添加字体文件 1、下载相关文件&#xff0c;放置文件夹中&#xff0c;这里我是在assets文件中新建了fontFamily 2、在assets文件中新建css文件 3、在页面中使用 <style lang"less" scoped> import ../../assets/css/fonts.less;.total-wrap {displa…

深度学习火车票识别系统 计算机竞赛

文章目录 0 前言1 课题意义课题难点&#xff1a; 2 实现方法2.1 图像预处理2.2 字符分割2.3 字符识别部分实现代码 3 实现效果4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 图像识别 火车票识别系统 该项目较为新颖&#xff0c;适…

详细介绍如何使用 SSD 进行实时物体检测:单次 MultiBox 探测器-含源码

介绍 在实时对象检测中,主流范例传统上采用多步骤方法,包括边界框、像素或特征重采样以及高质量分类器应用的提议。虽然这种方法已经实现了高精度,但其计算需求往往阻碍了其对实时应用的适用性。然而,单次多框检测器 (SSD) 代表了基于深度学习的对象检测的突破性飞跃。SSD…

rust中动态数组Vec的简单使用

在Rust中&#xff0c;Vector&#xff08;简称Vec&#xff09;是一个动态数组数据结构&#xff0c;它可以动态地增加或减少其容量。Vec是Rust标准库中的一个常见类型&#xff0c;非常适合用于存储和操作一系列相同类型的值。 Vec其实是一个智能指针&#xff0c;用于在堆上分配内…

自定义软件app定制开发的需求和趋势|企业网站小程序搭建

自定义软件app定制开发的需求和趋势|企业网站小程序搭建 随着智能手机的普及和移动互联网的快速发展&#xff0c;移动应用程序&#xff08;App&#xff09;成为人们日常生活和工作中必不可少的一部分。然而&#xff0c;市面上已有的应用程序并不能完全满足用户的个性化需求&…

编写测试用例的17个技巧

1、前言 测试用例是任何测试周期的第一步&#xff0c;对任何项目都非常重要。如果在此步骤中出现任何问题&#xff0c;则在整个软件测试过程中都会扩大影响。如果测试人员在创建测试用例模板时使用正确的过程和准则&#xff0c;则可以避免这种情况。 在本文中将分享一些简单而…

synchronized底层原理(一)

文章目录 1. 问题引入2. 相关概念3. Synchronized使用4. Synchronized底层原理1. 简介2. Monitor&#xff08;管程/监视器&#xff09;3. Java语言的内置管程synchronized4. Java对象的内存布局5. 如何使用MarkWord记录锁状态6. 偏向锁7. 轻量级锁 1. 问题引入 假设我们有1000…

PostGIS学习教程十:空间索引

PostGIS学习教程十&#xff1a;空间索引 回想一下&#xff0c;空间索引是空间数据库的三个关键特性之一。空间索引使得使用空间数据库存储大型数据集成为可能。在没有空间索引的情况下&#xff0c;对要素的任何搜索都需要对数据库中的每条记录进行"顺序扫描"。索引通…

在gitlab中使用gitlab-sshd替换ssh服务

参考&#xff1a;https://docs.gitlab.com/ee/administration/operations/gitlab_sshd.html 说明 gitlab-sshd 是 OpenSSH 的轻量级替代品&#xff0c;用于提供 SSH 操作。虽然 OpenSSH 使用受限的 shell 方法&#xff0c;但 gitlab-sshd 的行为更像是一个现代的多线程服务器应…

mabatis基于xml方式和注解方式实现多表查询

前面步骤 http://t.csdnimg.cn/IPXMY 1、解释 在数据库中&#xff0c;单表的操作是最简单的&#xff0c;但是在实际业务中最少也有十几张表&#xff0c;并且表与表之间常常相互间联系&#xff1b; 一对一、一对多、多对多是表与表之间的常见的关系。 一对一&#xff1a;一张…

【Maven】安装和使用

1. Maven 概述 Maven 是一款用于管理和构建 java 项目的工具&#xff0c;可以进行依赖管理、统一项目结构和项目构建。 1.1 Maven 模型 项目对象模型 (Project Object Model)依赖管理模型(Dependency)构建生命周期/阶段(Build lifecycle & phases) 1.2 Maven 仓库 仓库的…

ROS2教程01 ROS2介绍

ROS2介绍 版权信息 Copyright 2023 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. The author holds all right…

高级搜索——伸展树Splay详解

文章目录 伸展树Splay伸展树Splay的定义局部性原理Splay的伸展操作逐层伸展双层伸展zig-zig/zag-zagzig-zag/zag-zigzig/zag双层伸展的效果与效率 伸展树的实现动态版本实现递增分配器节点定义Splay类及其接口定义伸展操作左单旋右单旋右左/左右双旋伸展 查找操作删除操作插入操…

【laBVIEW学习】4.声音播放,自定义图标,滚动条设置,保存参数以及恢复参数

一。声音播放&#xff08;报错&#xff0c;未实现&#xff09; 1.报错4810 2.解决方法&#xff1a; 暂时未解决。 二。图片修改 1.目标&#xff1a;灯泡---》自定义灯泡 2.步骤&#xff1a; 1.右键点击--》自定义运行 表示可以制作自定义类型 2.右键--》打开自定义类型 这样就…

【Qt开发流程】之对象模型2:属性系统

描述 Qt提供了一个复杂的属性系统&#xff0c;类似于一些编译器供应商提供的属性系统。然而&#xff0c;作为一个独立于编译器和平台的库&#xff0c;Qt不依赖于非标准的编译器特性&#xff0c;如__property或[property]。 Qt解决方案适用于Qt支持的所有平台上的任何标准c编译…

java的GUI基础使用

java.awt包提供了基本的GUI设计工具&#xff0c;主要包括组件&#xff08;Component&#xff09;、容器&#xff08;Container&#xff09;和布局管理器&#xff08;LayoutManager&#xff09;&#xff1b; Java的图形用户界面的最基本组成部分是组件&#xff08;Component&…

Hadoop学习笔记(HDP)-Part.11 安装Kerberos

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

数据库事务:保障数据一致性的基石

目录 1. 什么是数据库事务&#xff1f; 1.1 ACID特性解析 2. 事务的实现与控制 2.1 事务的开始和结束 2.2 事务的隔离级别 3. 并发控制与事务管理 3.1 并发控制的挑战 3.2 锁和并发控制算法 4. 最佳实践与性能优化 4.1 事务的划分 4.2 批处理操作 5. 事务的未来发展…

odoo自定义提示性校验

背景: 在odoo16的原生的代码里&#xff0c;可以给按钮添加一个 confirm属性&#xff0c;从而达到 提示性校验的效果。 问题&#xff1a; 这个属性加了之后一定会弹出提示性校验的对话框&#xff0c;于是如何根据我们的实际业务&#xff0c;从后端返回提示性信息&#xff0c;…