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

1.无向图的连通分量

 图遍历时,对于连通图,无论是广度优先搜索还是深度优先搜索,仅需要调用一次搜索过程,即从任一个顶点出发,便可以遍历图中的各个顶点。对于非连通图,则需要多次调用搜索过程,而每次调用得到的顶点访问序列恰为各连通分量中的顶点集。

连通分量:无向图的极大连通子图

连通图只有一个连通分量,就是它本身

非连通图有多个连通分量

无向图的连通分量的求法:

从每个顶点出发进行遍历(深度或广度优先) 每一次从一个新的起点出发进行遍历得到的顶点序列就是一个连通分量的顶点集合。

2.无向网的最小生成树

生成树的性质:  

 每个连通图至少包含一颗生成树。  

 若G是(n,e)连通图,则e≥n-1    

对于有n 个顶点的无向连通图,无论其生成树的形态如何,所有生成树中都有且仅有n-1 条边。  

 如果无向连通图是一个网,那么,它的所有生成树中必有一棵边的权值总和最小的生成树,我们称这棵生成树为最小生成树,简称为最小生成树。  

生成树(Spanning Tree)

包含原连通图的所有n个顶点

包含原有的其中n-1条边

且保证连通(极小连通子图)

理解 :“包含所有顶点”:顶点一个都不能少

“极小”:那只能让边尽量少了

“连通”:但是又不能太少

应用:连通n个城市的需要多少条道路?

最多n(n-1)/2:任何两个城市之间都修一条路

最少n-1,问题是哪n-1条能使总代价最小呢?

问题转化为:如何在可能的路线中选择n-1条,能把所有城市(顶点)均连起来,且总耗费(各边权值之和)最小。

最小生成树不唯一,因为不同边的权值可能相等,当权值都相等时,就相当于无权图。 所有边权值均不相同的无向连通图的最小生成树是唯一的。 无论最小生成树是否唯一,但最小生成树的权值是唯一的。

最小生成树的性质(MST性质):

设连通网 N=(V,{E})

U为V的非空子集

F={(v1,v2)|(v1,v2)∈E,v1∈U,v2∈V-U}

设(u,v)是F中权值最小的边,则必存在一棵包含(u,v)的最小生成树

MST有多种算法,但最常用的是以下两种:

Prim算法特点: 将顶点归并,与边数无关,适于稠密网。(对顶点操作)

Kruskal算法特点:将边归并,适于求稀疏网的最小生成树。(对边操作)

 1. 普里姆算法( Prim算法)        

假设N=(V, {E})是连通网,TE为最小生成树中边的集合。      

(1) 初始U={u0}(u0∈V), TE=φ;      

(2)在所有u∈U,  v∈V-U的边中选一条代价最小的边(u0, v0)并入集合TE,同时将v0并入U;      

(3) 重复(2), 直到U=V为止。        

此时,TE中必含有n-1条边,则T=(V,{TE})为N的最小生成树。        

可以看出, 普利姆算法逐步增加U中的顶点, 可称为“加点法”。

所得生成树权值和:14+8+3+5+16+21 = 67

图采用邻接矩阵作为存储结构;

设置一个辅助数组closedge[ ]:  

lowcost域   存放生成树外顶点集合(V-U)中的各顶点到生成树内(U)各顶点的各边上的当前最小权值;

 adjvex域  记录生成树外顶点集合(V-U)各顶点距离树内集合(U)哪个顶点最近(即权值最小)。

struct{
	int adjvex;
	int lowcost;
 }closedge[MAX_VERTEX_NUM];


 

struct{
	int adjvex;
	int lowcost;
 }closedge[MAXVERTEXNUM];
void Prim(MGraph G,int v)
{   /*G为图的邻接矩阵存储,v是第一个进入集合U中的顶点的序号*/
	int k,j,i,minCost;
	closedge[v].lowcost=0;
	for (j=0;j<G.n;j++)            /*初始化closedge数组*/ 
		if (j!=v) 
		{  closedge[j].adjvex=v;
	                  closedge[j].lowcost=G.edges[v][j]; 
		}
for (i=1;i<G.n;i++)              /*依次将顶点加入到集合U中*/
{  
      for(j=0;j<G.n;j++)    /*定位第一个没有加入到U中的顶点*/
           if(closedge[j].lowcost!=0)
	{
	    k=j;
	    break;
	} 
      /*定位V-U集合中lowcost值最小的顶点*/
      minCost=closedge[k].lowcost; 
     for (j=0;j<G.n;j++)           /*查找权值最小的边*/
           if (closedge[j].lowcost <minCost && closedge[j].lowcost!=0)
            { 
	minCost=closedge[j].lowcost;
	k=j;
             } 

     /*输出新加入到树中的边*/
           printf("(%c,%c)\n",closedge[k].adjvex,G.vexs[k]); 
        closedge[k].lowcost=0;   /*将该顶点加入到集合U*/
	for (j=0;j<G.n;j++)      /*更新closedge数组的内容*/
	       if (G. edges[k][j]<closedge[j].lowcost)
		{ 
			closedge[j].adjvex=G.vexs[k];
			closedge[j].lowcost=G.edges[k][j];
		}
   }     /*for循环执行完毕,所有顶点均加入最小生成树*/
}        /*算法结束*/

普里姆算法中的第二个for循环语句频度为n-1,其中包含的两个内循环频度也都为n-1,因此普里姆算法的时间复杂度为O(n2)。普里姆算法的时间复杂度与边数e无关,该算法更适合于求边数较多的带权无向连通图的最小生成树。   

 2. 克鲁斯卡尔算法( Kruskal算法)      

假设N=(V, {E})是连通网,将N中的边按权值从小到大的顺序排列:      

(1) 将n个顶点看成n个集合;      

(2) 按权值由小到大的顺序选择边, 所选边应满足两个顶点不在同一个顶点集合内,将该边放到生成树边的集合中。同时将该边的两个顶点所在的顶点集合合并;      

 (3) 重复(2), 直到所有的顶点都在同一个顶点集合内。        

可以看出,克鲁斯卡尔算法逐步增加生成树的边, 与普里姆算法相比,可称为“加边法”。

为实现克鲁斯卡尔算法需要设置一维辅助数组E,按权值从小到大的顺序存放图的边,数组的下标取值从0到e-1(e为图G边的数目)。 假设数组E存放图G中的所有边,且边已按权值从小到大的顺序排列。n为图G的顶点个数,e为图G的边数。克鲁斯卡尔算法如下:

typedef struct
{ int vex1;                     //边的起始顶点
int vex2;                      //边的终止顶点
int weight;                    //边的权值
}Edge;
Void kruskal(Edge E[],int n,int e)
{ int i,j,m1,m2,sn1,sn2,k;
  int vset[MAXV];         //用于记录顶点是否属于同一集合的辅助数组
  for(i=0;i<n;i++)     vset[i]=i; //初始化辅助数组
   k=0;                             //表示当前构造最小生成树的第k条边,初值为0
  for(j=0;j<e;j++)                             //生成的边数小于e时继续循环
  { ml=E[j].vex1;m2=E[j].vex2;      //取一条边的两个邻接点
    sn1=vset[m1];sn2=vset[m2];     //分别得到两个顶点所属的集合编号
    if(sn1!=sn2)     //两顶点分属于不同的集合,该边是最小生成树的一条边
     { printf(“(%d,%d):%d\n”,m1,m2,E[j].weight);
       k++;                                          //生成边数增l
      if(k==n-1)  break;
     for(i=0;i<n;i++)
          if (vset[i]==sn1)  
                vset[i]=sn2;                    //修改集合编号相同
    }
  }
} 

 如果给定带权无向连通图G有e条边,且边已经按权值递增的次序存放在数组E中,则用克鲁斯卡尔算法构造最小生成树的时间复杂度为O (e)。克鲁斯卡尔算法的时间复杂度与边数e有关,该算法适合于求边数较少的带权无向连通图的最小生成树。

3.有向无环图(AOV)进行拓扑排序

AOV-网----拓扑排序(Topological Sort)

用顶点表示活动,用弧表示活动间的优先关系的有向无环图,称为顶点表示活动的网(Activity On Vertex Network),简称为AOV-网。

在有向图G=(V, {E})中, V中顶点的线性序列(vi1, vi2,  vi3 …,vin)称为拓扑序列,序列必须满足如下条件:

对序列中任意两个顶点vi、vj,在G中有一条从vi到vj的路径,则在序列中vi必排在vj之前。

AOV-网的特性如下:       

若vi为vj的先行活动,vj为vk的先行活动,则vi必为vk的先行活动,即先行关系具有可传递性。从离散数学的观点来看,若有<vi, vj>、 <vj, vk>,则必存在<vi, vk>。        

显然,在AOV-网中不能存在回路,否则回路中的活动就会互为前驱,从而无法执行。

 AOV-网的拓扑序列不是唯一的。      

拓扑排序的基本思想为:

(1) 从有向图中选一个无前驱的顶点输出;

 (2) 将此顶点和以它为起点的弧删除;

(3) 重复(1)、(2),直到不存在无前驱的顶点;      

(4) 若此时输出的顶点数小于有向图中的顶点数,则说 明有向图中存在回路,否则输出的顶点的顺序即为一个拓扑序列。 

int TopoSort (AdjList G)
    {Stack S; 
      int indegree[MAX-VERTEX-NUM]; 
      int i,  count,  k; 
      ArcNode *p; 
      FindID(G, indegree);    /*求各顶点入度*/
      InitStack(&S);          /*初始化辅助栈*/
      for(i=0; i<G.vexnum; i++)
             if(indegree[i]==0) Push(&S, i);      /*将入度为0的顶点入栈*/
      count=0; 
      while(!StackEmpty(S)) 
        {
 Pop(&S, &i); 
                   printf(″%c″, G.vertex[i].data); 
                   count++;   /*输出i号顶点并计数*/
                   p=G.vertexes[i].firstarc; 
                   while(p! =NULL)
                        {k=p->adjvex; 
                          indegree[k]--;        /*i号顶点的每个邻接点的入度减1*/
                          if(indegree[k]==0)  Push(&S,  k);   /*若入度减为0,则入栈*/
                          p=p->nextarc; 
                     }
               } /*while*/
     if (count<G.vexnum)  return(Error);   /*该有向图含有回路*/
     else  return(Ok); 
  } 

求顶点入度:

void FindID( AdjList G,   int indegree[MAX-VERTEX-NUM]) 
/*求各顶点的入度*/
   {int i;    ArcNode *p; 
    for(i=0; i<G.vexnum; i++)
      indegree[i]=0;   
    for(i=0; i<G.vexnum; i++)
        {p=G.vertexes[i].firstarc; 
         while(p!  =NULL)
            {indegree[p->adjvex]++; 
              p=p->nextarc; 
             } 
      } /* for */
   } 

4.有向无环网(AOE)的关键路径

AOV-网----关键路径

 有向图在工程计划和经营管理中有着广泛的应用。 通常用有向图来表示工程计划时有两种方法:

用顶点表示活动, 用有向弧表示活动间的优先关系, 即上节所讨论的AOV-网。        

用顶点表示事件, 用弧表示活动, 弧的权值表示活动所需要的时间。           

我们把用第二种方法构造的有向无环图叫做边表示活动的网(Activity On Edge  Network), 简称AOE-网。

用顶点表示事件,弧表示活动,弧上权值代表活动所需的时间duration of time,这样的有向图叫AOE(Activity On Edge Network)网。 AOE网常用于估算工程完成时间。

AOE网的特点:

1.只有在某个顶点所代表的事件发生以后,该顶点引发的活动才能开始。

2.进入某事件的所有边所代表的活动都已完成,该顶点所代表的事件才能发生。

在AOE网中存在唯一的、入度为零的顶点,叫做源点;

存在唯一的、出度为零的顶点,叫做汇点。

从源点到汇点的最长路径的长度即为完成整个工程任务所需的时间,该路径叫做关键路径。

关键路径上的活动叫做关键活动。

这些活动中的任意一项活动未能按期完成,则整个工程的完成时间就要推迟。相反,如果能够加快关键活动的进度,则整个工程可以提前完成。

关键路径:从源点到汇点的路径长度最长的路径叫关键路径。

关键路径的特点:

关键路径的长度(路径上的边的权值之和)为完成整个工程所需要的最短时间。

关键路径的长度变化(即任意关键活动的权值变化)将影响整个工程的进度,而其他非关键活动在一定范围内的变化不会影响工期。

注意事项:

1、求关键路径必须在拓扑排序的前提下进行,有环图不能求关键路径。

2、只有减少关键活动的时间才可能缩短工期。

3、只有减少所有关键路径上共有的关键活动的时间才可能缩短工期。(关键路径不唯一)

4、只有在不改变关键路径的前提下减少关键活动的时间才可能缩短工期

求关键路径的基本步骤如下:      

(1)对图中顶点进行拓扑排序,在排序过程中按拓扑序列求出每个事件的最早发生时间ET(i);     

(2) 按逆拓扑序列求每个事件的最晚发生时间LT(i);      

(3)求出每个活动ai的最早开始时间e(i)和最晚发生时间l(i);    

(4) 找出e(i)=l(i) 的活动ai, 即为关键活动。

//修改后的拓扑排序
int  ET[MAX-VERTEX-NUM];       /*每个顶点的最早发生时间*/
int TopoOrder(AdjList G,  Stack * T) 
/* G为有向网, T为返回拓扑序列的栈, S为存放入度为0的顶点的栈*/
{int count, i, j, k;   ArcNode *p; 
  int indegree[MAX-VERTEX-NUM];    /*各顶点入度数组*/
  Stack  S; 
  InitStack(T);   InitStack(&S);     /*初始化栈T,   S*/
  FindID(G,   indegree);    /*求各个顶点的入度*/
  for(i=0; i<G.vexnum; i++)
 if(indegree[i]==0)       Push(&S, i); 
    count=0; 
    for(i=0; i<G.vexnum; i++)
         ET[i]=0;     /*初始化最早发生时间*/
    while(!StackEmpty(S))
          {Pop(&S, &j); 
            Push(T, j); 
            count++; 
            p=G.vertex[j].firstarc; 
           while(p! =NULL)
                 {k=p->adjvex; 
                  if(--indegree[k]==0)  Push(&S, k);     /*若顶点的入度减为0
, 则入栈*/ 
  if (ET[j]+p->weight > ET[k]) 
                     ET[k]=ET[j]+p->weight; 
                p=p->nextarc;
             }  /*while*/
       } /*while*/
  if(count<G.vexnum)       return(Error); 
  else   return(Ok); 
} 
//关键路径
int  CriticalPath(AdjList G)
    {ArcNode  *p;  
      int  i, j, k, dut, ei, li;   char tag; 
      int  LT[MAX-VERTEX-NUM];     /*每个顶点的最迟发生时间*/
      Stack T; 
  if(!TopoOrder(G, &T))  return(Error); 
      for(i=0; i<G.vexnum; i++)
            LT[i]=ET[i];     /*初始化顶点事件的最迟发生时间*/
      while(!StackEmpty(T))    /*按逆拓扑顺序求各顶点的vl值*/
              { Pop(&T, &j); 
                 p=G.vertex[j].firstarc; 
                while(p! =NULL)
                     {k=p->adjvex;  dut=p->weight; 
                       if(LT[k]-dut<LT[j])  
                      LT[j]= LT[k]-dut; 
                       p=p->nextarc; 
                      } /* while */
                 } /* while*/
      for(j=0; j<G.vexnum; j++)    /*求ei, li和关键活动*/ 
 {p=G.vertex[j].firstarc; 
         while(p! =NULL)
              {k=p->Adjvex;  dut=p->weight; 
                ei=ET[j]; li=LT[k]-dut;  
                tag=(ei==li)?′*′: ′ ′; 
                printf(″%c, %c, %d, %d, %d, %c\n″, 
                      G.vertex[j].data, G.vertex[k].data, dut, ei, li, tag);   /*输出关键活动*/
                p=p->nextarc; 
 
              } /*while*/ 
         } /* for */ 
    return(Ok); 
} /*CriticalPath*/ 

5.有向网中顶点间的最短路径

两种常见的求最短路径问题的方法:

单源最短路径—用Dijkstra(迪杰斯特拉)算法(一顶点到其余各顶点,图中不能含负的权值)

所有顶点间的最短路径—用Floyd(弗洛伊德)算法(任意两顶点之间,一次求各对顶点间最短路径)

我们可以将图中的顶点分为两组:

 S——已求出的最短路径的终点集合(开始为{v0})。  

V-S——尚未求出最短路径的顶点集合(开始为V-{v0}的全部结点)。

 按最短路径长度的递增顺序逐个将第二组的顶点加入到第一组中。

一般情况下,下一条长度最短的最短路径的长度必是 dist[j]=Min{dist[i] | vi∈V-S}  其中,dist[i]或者是弧(v0,vi)上的权值, 或者是dist[k](vk∈S)和弧(vk,vi)上的权值之和。

1.Dijkstra算法

迪杰斯特拉算法的主要步骤如下:

 (1) g为用邻接矩阵表示的带权图。 S←{v0} , dist[i]= g.arcs[v0][vi];将v0到其余顶点的路径长度初始化为权值;

(2) 选择vk,使得 vk为目前求得的下一条从v0出发的最短路径的终点。

(3) 修改从v0出发到集合V-S上任一顶点vi的最短路径的长度。如果 dist[k]+ g.arcs[k][i]<dist[i] 则将dist[i]修改为 dist[k]+ g.arcs[k][i]

(4) 重复(2)、(3) n-1次,即可按最短路径长度的递增顺序,逐 个求出v0到图中其它每个顶点的最短路径。

typedef  SeqList VertexSet; 
ShortestPath-DJS(AdjMatrix  g,   int  v0,   
                             WeightType  dist[MAX-VERTEX-NUM],   
                             VertexSet  path[MAX-VERTEX-NUM] ) 
/* path[i]中存放顶点i的当前最短路径。 dist[i]中存放顶点i的当前最短路径长度*/
{ VertexSet  s;     /* s为已找到最短路径的终点集合*/
    for ( i =0; i<g.vexnum ; i++)        /*初始化dist[i]和path [i] */ 
{  InitList(&path[i]); 
    dist[i]=g.arcs[v0][i];  
    if ( dist[i]< INFINITY  
       {  AddTail(&path[i],   g.vexs[v0]);    /* AddTail为表尾添加操作*/
           AddTail(&path[i],   g.vexs[i]); 
        }
 } 
InitList(&s);  
AddTail(&s,   g.vexs[v0]);        /* 将v0看成第一个已找到最短路径的终点*/ 
for ( t = 1 ; t<=g.vexnum-1;  t++)  
    /*求v0到其余n-1个顶点的最短路径(n= g.vexnum )*/
    {min= INFINITY; 
      for ( i =0;  i<g.vexnum; i++)
          if (! Member(g.vex[i],   s) && dist[i]<min )  {k =i;  min=dist[i]; } 
AddTail(&s,   g.vexs[k]); 
for ( i =0;  i<g.vexnum; i++)      /*修正dist[i],   i∈V-S*/ 
    if (!Member(g.vex[i],   s) && (dist[k]+ g.arcs [k][i]<dist[i]))
        {dist[i]=dist[k]+ g.arcs [k][i]; 
           path[i]=path[k]; 
          AddTail(&path[i],   g.vexs[i]);    /* path[i]=path[k]∪{Vi} */
       } 
    }
} 

显然,算法的时间复杂度为O(n2) 。

2.Floyd算法

弗罗伊德算法的基本思想如下:        

设图g用邻接矩阵法表示,求图g中任意一对顶点vi、 vj间的最短路径 。

(-1) 将vi到vj 的最短的路径长度初始化为g.arcs[i][j], 然后进行如下n次比较和修正:

(0) 在vi、vj间加入顶点v0,比较(vi, v0, vj)和(vi, vj)的路径的长度,取其中较短的路径作为vi到vj的且中间顶点号不大于0的最短路径。

(1)  在vi、vj间加入顶点v1,得(vi, …,v1)和(v1, …,vj), 其中(vi, …, v1)是vi到v1 的且中间顶点号不大于0的最短路径, (v1, …, vj) 是v1到vj 的且中间顶点号不大于0的最短路径,这两条路径在上一步中已求出。 将(vi, …, v1, …, vj)与上一步已求出的且vi到vj 中间顶点号不大于0的最短路径比较,取其中较短的路径作为vi到vj 的且中间顶点号不大于1的最短路径。

 (2)在vi、vj间加入顶点v2,得(vi, …, v2)和(v2, …, vj), 其中(vi, …, v2)是vi到v2 的且中间顶点号不大于1的最短路径, (v2, …, vj) 是v2到vj 的且中间顶点号不大于1的最短路径,这两条路径在上一步中已求出。将(vi, …, v2, …, vj)与上一步已求出的且vi到vj 中间顶点号不大于1的最短路径比较, 取其中较短的路径作为vi到vj 的且中间顶点号不大于2的最短路径。

typedef  SeqList  VertexSet; 
ShortestPath-Floyd(AdjMatrix  g, WeightType  dist [MAX-VERTEX-NUM][MAX-VERTEX-NUM], VertexSet  path[MAX-VERTEX-NUM] [MAX-ERTEX-NUM] )
/* g为带权有向图的邻接矩阵表示法,  path [i][j]为vi到vj的当前最短路径,dist[i][j]为vi到vj的当前最短路径长度*/
{
 for (i=0;  i<g.vexnumn;  i++)    
    for (j =0; j<g.vexnum;  j++)
    { /*初始化dist[i][j]和path[i][j] */ 
 InitList(&path[i][j]); 
        dist[i][j]=g.arcs[i][j];  
         if (dist[i][j]<MAX)  
            {AddTail(&path[i][j],   g.vexs[i]); 
             AddTail(&path[i][j],   g.vexs[j]);   
           }
   }
 for (k =0; k<g.vexnum; k++)
   for (i =0; i<g.vexnum; i++)
      for (j=0; j<g.vexnum; j++)
         if (dist[i][k]+dist[k][j]<dist[i][j])   
          {
           dist[i][j]=dist[i][k]+dist[k][j];     
            paht[i][j]=JoinList(paht[i][k],  paht[k][j]);      
          }     /*JoinList为合并线性表操作*/
 } 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

二叉平衡树

一直想深入的研究一下&#xff0c;并手写平衡二叉树的插入、删除代码。 二叉树是动态查找的典范&#xff0c;但在极限情况下&#xff0c;二叉树的查找效果等同于链表&#xff0c;而平衡二叉树可以完美的达到 log ⁡ 2 n \log_2 n log2​n。 AVL简称平衡二叉树&#xff0c;缩写…

[Mac软件]HitPaw Photo Object Remover Mac v1.2.1 Ai智能去水印工具图像物体移除

多亏了HitPaw Photo Object Remover&#xff0c;它会自动跟踪和识别对象&#xff0c;并帮助您通过几个简单的步骤从照片中删除您想要的所有内容。 使用人工智能删除照片中物体的一流工具 •像1-2-3一样轻松地从照片中删除对象 •人工智能技术有助于立即清除不必要的物体 •轻…

激光雷达生成的图像检测关键点用来辅助里程计的方案

文章&#xff1a;LiDAR-Generated Images Derived Keypoints Assisted Point Cloud Registration Scheme in Odometry Estimation 作者&#xff1a;Haizhou Zhang , Xianjia Yu, Sier Ha , Tomi Westerlund 编辑&#xff1a;点云PCL 欢迎各位加入知识星球&#xff0c;获取PDF…

springboot 整合 Spring Security+JWT 实现token 认证和校验

1.大概是这个样子 JWT 是什么&#xff1f; Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准&#xff08;(RFC 7519).该token被设计为紧凑且安全的&#xff0c;特别适用于分布式站点的单点登录&#xff08;SSO&#xff09;场景。JWT的声明…

有源滤波器在矿区配电网中的应用

针对目前有源滤波器应用于矿区谐波治理时电网频率适应能力较低的问题&#xff0c;针对定采样点数字控制系统提出了一种具有频率自适应能力的谐振控制策略。该策略不仅可以实现对电网频率波动的自适应&#xff0c;提高滤波器补偿效果&#xff0c;而且不需要在线对控制器参数进行…

Apipost版IDEA插件

Apipost-Helper是由Apipost推出的IDEA插件&#xff0c;写完接口可以进行快速调试&#xff0c;且支持搜索接口、根据method跳转接口&#xff0c;还支持生成标准的API文档&#xff0c;注意&#xff1a;这些操作都可以在代码编辑器内独立完成&#xff0c;非常好用&#xff01;这里…

设计原则 | 依赖转置原则

一、依赖转置原则&#xff08;DIP&#xff1a;Dependence Inversion Principle&#xff09; 1、原理 高层模块不应该依赖低层模块&#xff0c;二者都应该依赖于抽象抽象不应该依赖于细节&#xff0c;细节应该依赖于抽象 2、层次化 Booch曾经说过&#xff1a;所有结构良好的面…

丢包问题定位(一)

1,原理图 从上图我们分两个部分,一部分是host测(靠近交换sdk测) ,一部分是line测(靠近光模块测) 这里我们靠近交换(与交换测连接的是retimer芯片)。 当设备丢包时我们怎么定位呢! 先弄清楚设备的连接情况,确认是模块问题,设备问题,还是参数问题,前两种是个例,…

利用udev 修改 网卡名称 的方法和规则文件不生效 可能的查找方法

为什么要修改? 服务器通常有多块网卡,有板载集成的,同时也有插在PCIe插槽的。Linux系统的命名原来是eth0,eth1这样的形式,但是这个编号往往不一定准确对应网卡接口的物理顺序。我们也希望能跟设备外部的丝印对的上 方法: 利用udev 机制。 在 /etc/udev/rules.d/ 下增加…

指针(二)

这里写目录标题 字符指针字符指针与常量字符串的区别&#xff1a; 指针数组数组指针两者的区别&#xff1a;&数组名 &#xff0c;sizeof(arr)数组指针的使用数组参数&#xff0c;指针参数一维数组传参整型数组&#xff1a;整型指针数组&#xff1a; 一级指针传参二级指针传…

配置REST API数据访问

大家好&#xff0c;才是真的好。 我希望你看过前一篇内容《Domino REST API安装和运行》。没有看过也没有关系&#xff0c;毕竟你可以点击上面的链接再去看一遍。 至于这一篇&#xff0c;趁热打铁&#xff0c;我们主要来讲述如何配置Domino Rest API的数据访问。 首先这里有…

电子学会C/C++编程等级考试2021年03月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:酒鬼 Santo刚刚与房东打赌赢得了一间在New Clondike 的大客厅。今天,他来到这个大客厅欣赏他的奖品。房东摆出了一行瓶子在酒吧上。瓶子里都装有不同体积的酒。令Santo高兴的是,瓶子中的酒都有不同的味道。房东说道:“你可以…

鸿蒙4.0开发笔记之ArkTS语法基础之条件渲染和循环渲染的使用(十五)

文章目录 一、条件渲染&#xff08;if&#xff09;二、循环渲染&#xff08;ForEach&#xff09; 一、条件渲染&#xff08;if&#xff09; 1、定义 正如其他语言中的if…else…语句&#xff0c;ArkTS提供了渲染控制的能力&#xff0c;条件渲染可根据应用的不同状态&#xff0…

计算机服务器中了locked勒索病毒的正确处理流程,locked勒索病毒解密

随着网络技术在企业生产运营中的进行&#xff0c;越来越多的企业开始利用网络走向数字化办公模式&#xff0c;数字化办公是企业的较为智能与先进的办公系统&#xff0c;这要求企业在日常工作中要确保计算机系统的安全&#xff0c;以防网络安全威胁时间的产生。近期&#xff0c;…

Image Segmentation Using Deep Learning: A Survey

论文标题&#xff1a;Image Segmentation Using Deep Learning:A Survey作者&#xff1a;发表日期&#xff1a;阅读日期 &#xff1a;研究背景&#xff1a;scene understanding,medical image analysis, robotic perception, video surveillance, augmented reality, and image…

光伏系统方案设计的注意点

随着太阳能技术的日益发展&#xff0c;光伏系统已经成为一种重要的可再生能源解决方案。然而&#xff0c;设计一个高效、可靠的光伏系统需要考虑到许多因素。本文将探讨光伏系统方案设计的注意点&#xff0c;包括系统规模、地理位置、组件选择、系统布局和运维策略。 系统规模 …

服务器——单个显卡的CPU占用比达到100%,但GPU使用率为0(卡住了)的解决办法

一、现象&#xff1a; 二、解决办法 先输入 htop&#xff0c;进入任务管理器。然后找到对应进程&#xff0c;按F9&#xff0c;再按一下9。

CVE初探之漏洞反弹Shell(CVE-2019-6250)

概述 ZMQ(Zero Message Queue)是一种基于消息队列得多线程网络库&#xff0c;C编写&#xff0c;可以使得Socket编程更加简单高效。 该编号为CVE-2019-6250的远程执行漏洞&#xff0c;主要出现在ZMQ的核心引擎libzmq(4.2.x以及4.3.1之后的4.3.x)定义的ZMTP v2.0协议中。 这一…

etcd 与 Consul 的一致性读对比

本文分享和对比了 etcd 和 Consul 这两个存储的一致性读的实现。 作者&#xff1a;戴岳兵&#xff0c;爱可生研发中心工程师&#xff0c;负责项目的需求开发与维护工作。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 本…

如何从eureka-server上进行服务发现,负载均衡远程调用服务

在spring cloud的maven的pom文件中添加eureka-client的依赖坐标 <!--eureka-client依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependen…