【数据结构】图

一.图的定义

1.定义:

图G由顶点集V和关系集E组成,记为G=(V,E)

注:图可以没有边,但不能没有顶点。

2.图的分类:

图的顶点数为n,边数为e

有向图:$0\leqslant e \leqslant n(n-1)$

无向图:$0\leqslant e\leqslant \frac{n(n-1)}{2}$

若:$e=n(n-1)$,则为有向完全图。

3.图的基本概念:

(1)权:与图的边或弧相关的数

(2)网:边或弧上带有权值的图

(3)顶点的度TD(V)

对于有向图来说:TD(V)=ID(V)+OD(V)

(4)生成树

设无向图G是含有n个顶点的连通图,则图G的生成树是含有n个顶点,且只有n-1条边的连通子图

二.图的存储

1.邻接矩阵

1.1

设图G=(V,E)有n个顶点,e条边。

则G的邻接矩阵为n阶方阵A,其中A满足:

$ A[i,j]= \begin{cases} 1 & if (v_i,v_j) or <v_i,v_j> \in E \\ 0 & if (v_i,v_j) or <v_i,v_j> \notin E \\ \end{cases} $

1.2 邻接矩阵的特点:

(1)判定两个顶点$v_i,v_j$之间是否关联,只需要判断$a_{ij}$是否为1

(2)容易求顶点的度

对于无向图来说:

$TD(v_i)=\sum_{j=1}^{n}{a_{ij}}$$=\sum_{i=1}^{n}{a_{ji}}$

对于有向图来说:

$TD(v_i)=OD(v_i)+ID(v_i)=\sum_{j=1}^{n}a_{ij}+\sum_{i=1}^{n}a_{ji}$

1.3 带权图的邻接矩阵

$ A[i,j]= \begin{cases} w_{ij} &if (v_i,v_j)or <v_i,v_j>\in E (i\not\neq j)\\ \infty & if (v_i,v_j)or <v_i,v_j>\notin E (i\not\neq j)\\ 0 & (i=j) \\ \end{cases} $

1.4 不带权的无向图的代码实现

template <class T>
class MGraph{
private:T vertex[MAX_SIZE];//每个顶点中的信息int arc[MAX_SIZE][MAX_SIZE];//存储邻接矩阵的二维数组int n,e;//图的顶点数和边数
public:MGraph(int n,int e,T v[]);};
template <class T>
MGraph<T>::MGraph(int n,int e,T v[]){int vi,vj;this->n=n;this->e=e;for(int i=0;i<n;i++){for(int j=0;j<n;j++){arc[i][j]=0;}vertex[i]=v[i];}for(int i=0;i<e;i++){cin>>vi>>vj;arc[vi][vj]=1;arc[vj][vi]=1;}
}

2.邻接表 

(1)结构数组(存储图中的顶点)

vertexfirstedge

(2)邻接点域(每个顶点的邻接点信息)

adjvexnext

2.1无向图邻接表的特点:

1)n个顶点,e条边的无向图,需要n个表头结点,2e个链表结点。

2)顶点$v_i$的度$TD(v_i)$=对应firstedge中结点数

2.2有向图邻接表的特点:

1)n个顶点,e条边的有向图,需要n个表头结点,e个链表结点。

2)顶点$v_i$的出度=对应firstedge中结点数;即:求某个顶点的出度容易,求入度难。

2.3有向图的逆邻接表的特点:

1)n个顶点,e条边的有向图,需要n个表头结点,e个链表结点。

2)顶点$v_i$的入度=对应firstedge中结点数;即:求某个顶点的入度容易,求出

度难。

2.4 有向图的无权邻接表代码实现:

struct vnode{int pos;struct node *next;
};
template <class T>
struct vertexNode{T vertex;struct vnode *firstedge;
};template <class T>
class AlGraph{
private:struct vertexNode <T> vertex[MAX_SIZE];int n;int e;
public:AlGraph(int n,int e,T v[]);~AlGraph();
};
template <class T>
AlGraph<T>::AlGraph(int n,int e,T v[]){int vi,vj;struct vnode *p;this->e=e;this->n=n;for(int i=0;i<n;i++){vertex[i].vertex=v[i];vertex[i].firstedge=NULL;}for(int i=0;i<e;i++){cin>>vi>>vj;p=new struct vnode;p->pos=vj;p->next=vertex[i].firstedge->next;vertex[i].firstedge=p;}
}
template <class T>
AlGraph<T>::~AlGraph<T>(){struct vnode *p;for(int i=0;i<n;i++){p=vertex[i].firstedge;if(p){while(p){vertex[i].firstedge=p->next;delete p;p=vertex[i].firstedge;}}}
}

2.5 十字链表 (orthogonal list)

由于邻接表求出度容易,而逆邻接表求入度容易,可以将其改造为十字链表,将邻接表和逆邻接表结合起来。

1)顶点结点:

datafirstinfirstout

data:存放顶点的有关信息

firstin:指向以该顶点为弧头的第一个弧结点

firstout:指向以该顶点为弧尾的第一个弧结点

2)弧结点:

tailvexheadvexhlinktlink

tailvex:指示该弧的弧尾顶点

headvex:指示该弧的弧头顶点

hlink:指向弧头相同的下一条弧

tlink:指向弧尾相同的下一条弧

通过hlink将弧头相同的弧连在一个链表上

通过tlink将弧尾相同的弧连在一个链表上

3)十字链表的特点:

顶点结点数等于顶点数

弧结点数等于弧的条数 

4)求顶点$V_i$入度和出度:

出度:从顶点的firstin出发,沿着弧结点的hlink所经过的弧结点数

入度:从顶点的firstout出发,沿着弧结点的tlink所经过的弧结点数

#include <iostream>
using namespace std;const int MAX_SIZE=10;
//弧结点
struct arc{int tailvex;int headvex;struct arc *hlink;struct arc *tlink;
};
//顶点结点
struct vertex{int data;struct arc *firstin,*firstout;
};class OrthGraph{
private:struct vertex v[MAX_SIZE];int vertexNum;int arcNum;
public:OrthGraph(int n,int e);~OrthGraph();
};
OrthGraph::OrthGraph(int n,int e){vertexNum=n;arcNum=e;int vi,vj;struct arc *p;for(int i=0;i<n;i++){v[i].data=i;v[i].firstin=NULL;v[i].firstout=NULL;}for(int i=0;i<e;i++){cin>>vi>>vj;p=new struct arc;p->headvex=vi;p->tailvex=vj;p->hlink=NULL;p->tlink=NULL;if(v[vi].firstin==NULL){p->hlink=v[vi].firstin;v[vi].firstin=p;}else{struct arc *q=v[vi].firstin;while(q->hlink){q=q->hlink;}q->hlink=p;}if(v[vj].firstout==NULL){p->tlink=v[vj].firstout;v[vj].firstout=p;}else{struct arc *q=v[vj].firstout;while(q->tlink){q=q->tlink;}q->tlink=p;}}
}
OrthGraph::~OrthGraph(){struct arc *p,*q;for(int i=0;i<vertexNum;i++){p=v[i].firstin;while(p){v[i].firstin=p->hlink;delete p;p=v[i].firstin;}p=v[i].firstout;while(p){v[i].firstout=p->tlink;delete p;p=v[i].firstout;}}
}

3.图的邻接矩阵和邻接表的比较 

(1)一个图的邻接矩阵表示是唯一的,邻接表不唯一。

(2)邻接表(逆邻接表)的空间复杂度为S(n,e)=O(n+e)。

(3)稀疏图选取邻接表;稠密图选择邻接矩阵。

(4)判断边,邻接矩阵比邻接表容易;求边数,邻接矩阵的时间复杂度为O($n^2$),邻接表中的复杂度为O(n+e)

(5)求有向图顶点的度,邻接矩阵更加方便;因为,邻接表求出度容易,而逆邻接表求入度容易。

三.图的遍历

1.定义:

从图中某个顶点出发,沿路径使图中每个顶点被访问且仅被访问一次的过程。

  • 深度优先搜索
  • 广度优先搜索

2.深度优先搜索DFS(depth-first-search)

 2.1 深度优先搜索遍历图的过程为:

1)访问指定的某顶点v,将v作为当前顶点;

2)访问当前顶点未被访问过的邻接点,并将该邻接点作为当前顶点;

3)重复2),直到当前顶点的所有邻接点都被访问过;

4)沿搜索路径回退,退到尚有邻接点未被访问过的某结点,将该结点作为当前结点,重复2),直到所有顶点都被访问完为止。

2.2 深度优先遍历的递归算法代码实现:

template <class T>
void MGraph<T>::DFS(int start){static bool visted[n]={false};int w;visted[start]=true;for(int i=0;i<n;i++){if(arc[start][i]==1&&visted[i]==false){w=i;DFS(w);}}
}

2.3 深度优先遍历的非递归算法代码实现:

template <class T>
void MGraph<T>::DFS_non_recursion(int start){int w,i;stack<int> s;static bool visited[n]={false};//源点压栈s.push(start);while(!s.empty()){w=s.top();//弹栈s.pop();visited[w]=true;//访问过cout<<w<<" ";for(i=0;i<n;i++){if(arc[w][i]&&!visited[i]){//存在边并且没有被访问过s.push(i);}}}}

3.广度优先遍历BFS(breadth- first-search)

3.1 广度优先遍历图的过程为:

1)首先访问指定顶点$v_0$,将$v_0$作为当前顶点;

2)访问当前顶点的所有未访问过的邻接点,并依次将访问的这些邻接点作为当前顶点;

3)重复2,直到所有顶点被访问为止。

3.2 广度优先遍历图的代码实现:

template <class T>
void MGraph<T>::BFS(int start){int v,w,i,count=0;queue<int> s;static bool visited[n]={false};v=start;visited[v]=true;cout<<v<<" ";++count;s.push(v);//初始化队列while(!s.empty()){if(count==n){return;}//获取队头元素,访问当前结点的所有邻接点v=s.front();s.pop();for(i=0;i<n;i++){if(arc[v][i]&&!visited[i]){w=i;cout<<w<<" ";++count;visited[w]=true;s.push(w);}}}
}

四.最小生成树

 1.引例:

N台计算机之间建立通讯网:

  • n台计算机中的任意两台能通过网络进行通讯。
  • 使总的通讯距离最短

2.最小生成树(Minimal Spanning Tree):

 1)找到一个生成树

2)确保生成树中边的权值和最小

3.MST性质:

假设G=(V,E)是一个无向连通网,U是顶点集V的一个非空子集。若(u,v)是一条具有最小权值的边,其中u属于U,v属于V-U,则必存在一棵包含边(u,v)的最小生成树。

 4.Prim算法

基本思想:设G=(V,E)是具有n个顶点的连通网,T=(U,TE)是G的最小生成树,T的初始状态为U={$u_0 $},TE={},重复执行下述操作:找一条代价最小的边(u,v)并入合集TE,同时v并入U,直至U=V。

5.Prim算法的代码实现

注:

如何将顶点加入到集合U中?

shortEdge[i].lowcost=0;

template <class T>
void MGraph<T>::Prim(int start){struct edge shortEdge[n];int i,j,k;shortEdge[start].lowcost=0;//起点放入集合U中//初始化shortEdge数组for(i=0;i<n;i++){shortEdge[i].adjvex=start;shortEdge[i].lowcost=arc[start][i];}for(i=0;i<n-1;i++){k=minEdge(shortEdge);//寻找最短边的邻接点koutputMST(k, shortEdge);//输出最小生成树路径shortEdge[k].lowcost=0;//将顶点k加入到集合U中for(j=0;j<n;j++){//调整shortEdge数组if(arc[k][j]>0&&shortEdge[j].lowcost==-1){//新加入的顶点有边并且j表示的顶点集合U到达不了shortEdge[j].adjvex=k;shortEdge[j].lowcost=arc[k][j];}else if(arc[k][j]>0&&shortEdge[j].lowcost>0&&arc[k][j]>shortEdge[j].lowcost){shortEdge[j].lowcost=arc[k][j];shortEdge[j].adjvex=k;}}}
}template <class T>
int MGraph<T>::minEdge(struct edge shortEdge[]){int i,j,min;for(i=0;i<n;i++){if(shortEdge[i].lowcost>0){min=i;break;}}for(i=0;i<n;i++){if(shortEdge[i].lowcost>0&&shortEdge[i].lowcost<shortEdge[min].lowcost){min=i;break;}}return min;
}template <class T>
void MGraph<T>::outputMST(int k,struct edge shortEdge[]){cout<<"("<<shortEdge[k].adjvex<<","<<k<<")"<<shortEdge[k].lowcost<<endl;
}

伪代码:

1.根据源点对shortEdge数组进行初始化。

2.进入循环

3.找到shortEdge数组中权值最小的边对应的顶点

4.将该顶点加入到集合U中 

5.由于集合U中新加入了顶点,则调整shortEdge数组

6.时间复杂度分析:

        外重循环是将每一个顶点加入到集合U中,内层循环是根据新加入的顶点来调整shortEdge数组的值。

        所以时间复杂度为$O(n^2)$

7.Kruskal算法:

逐步给生成树T中添加不和T中的边构成回路的当前最小代价边。

思想:

1.置生成树T的初始状态为T=$(V,\varnothing)$

2.当T中边数<n-1时,重复下列步骤:

从E中选取代价最小的边(v,u)

若:(v,u)与已有边集中的边没有形成回路,则将边(v,u)并入到T的边集中

否则,舍去该边,选择下一条代价最小的边

 问题的关键在于:

如何判断是否形成回路\rightarrow如何判别被考察边的两个顶点是否位于两个连通分量\rightarrow所属的树是否有相同的根节点

Kruskal算法实质上是使生成树以一种随意的方式生长,初始时,每个顶点构成一颗生成树。然后,每生长一次,就将两棵树合并,到最后合并成一棵树。

因此,可以设置一个数组parent[n],元素parent[i]表示顶点i的双亲结点,初始时,parent[i]=-1,表示顶点i没有双亲,即该结点是所在生成树的根节点;对于边(u,v),设vex1和vex2分别表示两个顶点所在树的根结点,如果vex1!=vex2,则顶点u和v必位于不同的连通分量,令parent[vex2]=vex1,实现将两棵树合并。

struct edge{//V和U-V之间的边int adjvex;int lowcost;
};struct EdgeType{int from,to;int weight;
};struct EdgeGraph{int vertex[MAX_SIZE];struct EdgeType edge[MAX_SIZE];int vertexNum,edgeNum;
};void outPutMST(EdgeType edge){cout<<"("<<edge.from<<","<<edge.to<<")"<<edge.weight<<endl;
}int findRoot(int parent[],int v){int t=v;while(parent[t]>-1){t=parent[t];}return t;
}void Kruskal(struct EdgeGraph G){//为了确保新加入边不会形成回路,则其两个顶点位于不同的连通分支中,那么问题转化为//如何确定其位于不同的连通分支//答案是,用一个parent数组来记录一下根结点int i,num=0,vex1,vex2;int parent[G.vertexNum];for(i=0;i<G.vertexNum;i++){//parent数组初始化parent[i]=-1;}//此处需要对edge数组按照权值进行从高到低排序for(i=0;i<G.edgeNum;i++){vex1=findRoot(parent,G.edge[i].from);vex2=findRoot(parent,G.edge[i].to);if(vex1!=vex2){//不在同一个连通分量重,合并outPutMST(G.edge[i]);parent[vex2]=vex1;//合并生成树num++;if(num==G.vertexNum-1){return;}}}}

 8.Kruskal与Prim算法的比较

Prim算法:

1)以连通为主

2)选择保证连通的代价最小的邻接边(n-1)次

3)时间复杂度与边无关  $O(n^2)$

4)适合求边稠密的最小生成树

Kruskal算法:

1)以最小代价边为主

2)添加不形成回路的当前最小代价边

3)算法时间复杂度与边有关 $O(elog_2{e})$

4)适合求边稀疏的最小生成树

五.最短路径问题

1.最短路径问题的描述:

在有向图中,寻找从源点到其余各个顶点或者每一对顶点之间的最短带权路径的运算

2.Dijkstra算法(单源点最短路径问题):

主要思想:

给定源点v,需要获取v到其余顶点的最短路径。

需要一个辅助数组dist,记录源点到其他顶点之间的距离。

依次加入顶点,每加入一个顶点,考察源点到其他顶点之间的距离是否缩短,如果缩短,更新dist和path数组。

1)由于需要频繁读取边的信息,所以采用邻接矩阵的存储方式

2)使用dist数组,这个数组用于记录从源点到每个终点的最短路径长度,初始值用arc[v][i]初始化,自己到自己记为0,到达不了记为$\infty$,其余记为权值。

3)path数组用于记录路径,初始值全部用源点来初始化,含义为从某个顶点到该顶点。如果新加入的顶点使距离变短,则更新path数组。path[i]存放i的直接前驱

4)s数组存放源点和已生成的终点,其初态为只有一个源点v。s[i]=1表示i顶点被存放进s数组中。

伪代码:

1.初始化数组dist、path和s;

2.while(s中的元素个数<n)

        2.1 在dist[n]中求最小值,其下标为k;

        2.2 输出dist[i]和path[j];

        2.3 修改数组dist和path;

        2.4 将顶点vk添加到数组s中

3.Floyd算法(多源点最短路径问题):

 如何求每一对顶点之间的最短路径?

每次以一个顶点为源点,调用Dijkstra算法n次 时间复杂度为$O(n^3)$

另一种求解思路:Floyd算法

基本思想:

1)用邻接矩阵来存储边。

2)外层循环:依次加入顶点,考察加入顶点后,对于路径长度是否有变化。

3)加入一个顶点,考察n个顶点

4)对于每一个顶点来说,需要考察其与n个顶点之间的距离,需要修改距离,则更新arc[][]数组,并且更新路径数组

算法时间复杂度为:$O(n^3)$

六.AOV网与拓扑排序

1.AOV网

在一个表示工程的有向图中,用顶点表示活动,用表示活动之间的优先关系。这样的有向图为顶点表示活动的网,我们称为AOV网(Activity On Vertex Network)

2.AOV网的特点:

(1)AOV网中的弧表示活动之间存在的某种制约关系

(2)AOV网中不能出现回路

3.拓扑排序:

拓扑序列:设G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列$v_1,v_2,...,v_n$称为一个拓扑序列,当且仅当满足下列条件:若从顶点$v_i$$v_j$有一条路径,则在顶点序列中顶点$v_i$必在$v_j$之前。

拓扑排序:对一个有向图构造拓扑序列的过程 

注:

1)拓扑排序是一种对非线性结构的有向图进行线性化的重要手段。

2)可以检查有向图中是否存在回路。

3)AOV网可以解决如下问题:

  • 判定工程的可行性。如果有回路,工程无法结束。
  • 确定各项活动在整个工程中执行的先后顺序。 

4.拓扑排序的基本思想:

(1)从AOV网中选择一个没有前驱的顶点并且输出;

(2)从AOV网中删除该顶点,并且删去所有以该顶点为弧头的的弧;

(3)重复上述两步,直到全部顶点都被输出,或AOV网中不存在没有前驱的顶点。

注:

1)没有前驱的顶点即:入度为0的顶点

2)删除以它为弧头的弧即:将该结点所有的直接后继结点的入度-1

由此:

选取存储结构时:

  • 容易得到各顶点的入度
  • 容易寻找到该顶点的直接后继

使用邻接表作为AOV网的存储结构,并在头结点中增加一个存放顶点入度的域indegree

我们还需要一个栈来存储所有没有前驱的顶点

5.拓扑排序的伪代码

1.栈S初始化,累加器count初始化;

2.扫描顶点表,将没有前驱的顶点压栈;

3.当栈非空时循环:

        3.1  保存弹栈元素,输出 ,累加器加一;

        3.2 将顶点的各个邻接点的入度减一;

        3.3 将新的入度为0的顶点入栈;

4.如果count<vertexNum,则图中有回路

七.AOE网与关键路径

1.AOE网的定义(Activity On Edge NetWork):

        在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动边上的权值表示活动的持续时间,称这样的有向图叫做边表示活动的网,简称AOE网。AOE网中没有入边的顶点称为始点(或源点),没有出边的顶点称为终点(或汇点)。

2.AOE网的性质:

1.只有在某顶点所代表的事件发生后,从该顶点出发的各活动才能开始;

2.只有在进入某顶点的各活动都结束,该顶点所代表的事件才能发生。

3.AOE网可以解决的问题:

1)可以知道完成整个工程至少需要多少时间

2)为缩短完成工程所需的时间,应当加快哪些活动,即:找出哪些活动是影响整个工程进展的关键。

4.关键路径与关键活动:

1)关键路径:

在AOE网中,从始点到终点具有最大路径长度(该路径上各个活动所持续的时间之和)的路径称为关键路径。

2)关键活动:

关键路径上的活动称为关键活动

5.术语:

1)事件的最早发生时间ve[k]

从始点开始到顶点$v_k$的最大路径长度,这个长度决定了所有从顶点$v_k$发出的活动能够开工的最早时间。

\left\{ \begin{aligned} &ve[1]=0\\ &ve[k]=max\{ve[j]+len<v_j,v_k>\}(<v_j,v_k>\in p[k])\\ \end{aligned} \right.

p[k]表示所有到达$v_k$的有向边的集合。

2)事件的最迟发生时间vl[k]

vl[k]是指在不推迟整个工期的前提下,事件$v_k$允许的最晚发生时间

$ \left\{ \begin{aligned} &vl[n]=ve[n] \\ &vl[k]=min\{vl[j]-len<v_k,v_j>\} (<v_k,v_j>\in s[k])\\ \end{aligned} \right. $

从后往前推算结点的vl值

3)活动的最早开始时间ee[i]

若活动$a_i$是由弧$<v_k,v_j>$表示,则活动$a_i$的最早开始时间等于事件$v_k$的最早发生时间

即:ee[i]=ve[k]

4)活动的最晚开始时间el[i]

若活动$a_i$是由弧$<v_k,v_j>$表示,则活动$a_i$的最晚开始时间要保证事件$v_j$的最迟发生时间不拖后

即:$el[i]=vl[j]-len<v_k,v_j>$

6.关键活动的确定

最后计算各个活动的时间余量el[k]-ee[k],时间余量为0即为关键活动 

7.关键路径算法的伪代码

1)从源点$v_0$出发,令ve[0]=0,按拓扑排序求其余各顶点的最早发生时间ve[i];

2)如果得到的拓扑排序中顶点个数小于AOE网中的顶点数,则说明网中存在环,不能求关键路径,算法终止;否则执行步骤3;

3)从终点v_{n-1}出发,令vl[n-1]=ve[n-1],按照逆序拓扑排序求其余各顶点的最迟发生时间vl[i];

4)根据各顶点的ve和vl值,求每条有向边的最早开始时间ee[i]和最迟开始时间el[i];

5)若某条有向边$a_i $满足条件ee[i]=el[i],则$a_i $为关键活动。

8.缩短工程时间

1)适当提高对应关键路径上的关键活动的速度,保证不改变AOE网的关键路径的前提下。

2)同时提高AOE网上的关键路径上关键活动的速度。

9.关键路径的代码实现

八.贪心算法

1.贪心算法的定义:

贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解

2.贪心算法的步骤:

1.建立数学模型来描述问题;

2.把求解的问题分成若干个子问题;

3.对每一个子问题求解,得到子问题的局部最优解;

4.把子问题的局部最优解合成原来问题的解。

3.贪心算法的基本要素:

1)贪心选择性质:

整体最优解可以通过一系列局部最优的选择得到

2)最优子结构性质:

子问题的最优解包含在原问题的最优解中

4.贪心算法的应用——活动安排问题:

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

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

相关文章

非负矩阵之Perron-Frobenius定理

1. 矩阵论记号约定 2. 非负矩阵之Perron-Frobenius定理 1907 年 O. Perron 发现正矩阵的谱有特别有趣的性质。G. Frobenius 在 1908-1912 年间将 Perron 的工作推广到不可约非负矩阵的情形&#xff0c;并得到了新的进一步结果。 Oskar Perron 在1907年发表了关于正矩阵的一些基…

建议把英语改成选修的计算机老师,越来越多的人建议高中将英语作为选修课,而非必修课,您认同吗?...

很多粉丝家人给白老师留言&#xff0c;说英语应该作为选修课&#xff0c;而不是必修课&#xff0c;因为英语学习影响了太多的学生&#xff0c;尤其是那些有真正才华的学生&#xff0c;而且英语学习又不实用&#xff0c;只是为了考试而已&#xff0c;问我是否认同这种说法&#…

hazelcast 使用_使用Hazelcast发布和订阅

hazelcast 使用几周前&#xff0c;我写了一篇有关Hazelcast入门的博客&#xff0c;描述了创建分布式地图&#xff0c;列表和队列是多么简单。 当时我提到&#xff0c;Hazelcast还做很多其他事情。 该博客快速介绍了Hazelcast的另一个功能&#xff1a;基于Publish / Subscribe模…

谱半径

矩阵的谱或叫矩阵的谱半径&#xff0c;在特征值估计、广义逆矩阵、数值分析以及数值代数等理论的建树中&#xff0c;都占有极其重要的地位&#xff1b; 矩阵的谱半径为矩阵的特征值的模的最大值。 关于矩阵的谱&#xff08;半径&#xff09;的一个重要性质即是&#xff1a;任意…

矩阵迹(trace), 行列式(determinate)

1. 迹&#xff08;trace&#xff09; 矩阵的迹&#xff08;trace&#xff09;表示矩阵 A AA 主对角线所有元素的和 迹的来源 最根本的应该就是迹和特征值的和相等。因为特征值如此重要&#xff0c;所以才定义了迹。离开了这一点&#xff0c;我觉得迹也就失去了立足点。 迹…

计算机的四个硬盘有什么区别是什么意思,笔记本的内存和硬盘有什么区别 原来笔记本硬盘有这几种...

之前有很多人分不清笔记本的内存和硬盘有何区别&#xff0c;很容易发生“内存128GB”的笑话&#xff0c;那么到底硬盘和内存有和区别?如何判断内存好坏呢?我想你应该看看这篇文章。笔记本内存内存是PC中的重要一环&#xff0c;是数据存放和交换的空间&#xff0c;所以内存容量…

抖音上发的测体重的软件怎么测试,抖音手机称重是什么软件 怎么用iPhone苹果手机称重方法...

抖音手机称重是最近很流行的&#xff0c;直接将想要称重的东西放在手机上&#xff0c;我们就可以知道物品的重点了&#xff0c;看上去很有意思&#xff0c;很多人都在玩。而抖音手机称重是什么软件呢&#xff1f;文中为大家介绍。抖音手机称重是什么软件称重计&#xff1a;Touc…

最小/大加代数(Min/max-Plus Algebra)

最小加代数 最小加代数最初是用于数字电路、通信网络以及制造工业等离散事件系统( Discrete Event Systems)建模的一种数学工具。在最小加代数中&#xff0c;下面两个运算符经常用到&#xff1a; 最大加代数 https://www.jianshu.com/p/c9847bb31834

计算机上播放时没声音什么故障,事实:在笔记本电脑上播放歌曲时如果没有声音怎么办...

在笔记本电脑上播放时如果没有声音该怎么办&#xff1f;关于在笔记本电脑上播放时无声音的问题&#xff0c;有些网民仍然不知道该怎么办&#xff0c;所以让我告诉您如何在笔记本电脑上播放无声音时解决问题。希望我能为您服务&#xff01;播放歌曲时&#xff0c;笔记本电脑没有…

martingale、markov chain、Monte Carlo、MCMC

文章结构如下&#xff1a; 1: MCMC 1.1 MCMC是什么 1.2 为什么需要MCMC 2&#xff1a; 蒙特卡罗 2.1 引入 2.2 均匀分布&#xff0c;Box-Muller 变换 2.3 拒绝接受采样&#xff08;Acceptance-Rejection Sampling&#xff09; 2.4 接受拒绝采样的直观解释 2.5 接受拒绝采样方…

Java“地铁”表(JavaFX)

再次嗨&#xff0c;这次&#xff0c;TableView“ Metro”样式被添加到JMetro JavaFX主题。 这会将JMetro版本放大到3.1.0。 我之所以没有添加表格样式&#xff0c;是因为奇怪的是在Fluent设计系统&#xff08;以前是Metro&#xff09;中还没有表格的定义。 有一个名为DataGrid…

razer鼠标测试软件,比HERO更强么,雷蛇FOCUS+引擎蝰蛇V2精准度测试

在鼠标引擎上&#xff0c;罗技HERO曾经一枝独秀&#xff0c;虽然赛睿有TrueMove、冰豹有Owl-Eye夜枭&#xff0c;但都不具备低功耗的特性&#xff0c;只能归类为传统游戏类引擎。作为体量接近罗技的一线品牌&#xff0c;雷蛇成为了一些人期待与之抗衡的希望&#xff0c;在毒蝰/…

rest spring_Spring REST:异常处理卷。 3

rest spring这是该系列中有关Spring REST异常处理的最后一篇文章。 最后&#xff0c;这次我将讨论在表单处理期间可能发生的REST异常的处理。 因此&#xff0c;在本教程中&#xff0c;您将看到与REST&#xff0c;表单和异常处理有关的所有内容。 客户端呢&#xff1f; JQuery将…

计算机季度函数,季度怎么分月份(根据月份函数生成季度)

小伙伴们好&#xff0c;咱们知道&#xff0c;Excel中的日期计算函数非常丰富&#xff0c;有用于计算年份的YEAR函数&#xff0c;有计算月份的MONTH函数&#xff0c;有计算星期的WEEKDAY函数等等。小伙伴们好&#xff0c;咱们知道&#xff0c;Excel中的日期计算函数非常丰富&…

泊松分布和指数分布

一、泊松分布 1.1 泊松分布的定义 日常生活中&#xff0c;大量事件是有固定频率的。 某医院平均每小时出生3个婴儿某公司平均每10分钟接到1个电话某超市平均每天销售4包xx牌奶粉某网站平均每分钟有2次访问 它们的特点就是&#xff0c;我们可以预估这些事件的总数&#xff0…

Gradle多项目构建–类似父pom的结构

当您来自Maven背景时&#xff0c;很可能已经习惯了父pom结构。 现在&#xff0c;在进行gradle时&#xff0c;情况有所不同。 想象一下有一个包含接口和各种其他实现的项目的场景。 这将是我们的项目结构。 multi-project-gradle -- specification -- core -- implementati…

移动办公计算机,最适合移动办公的三款掌上电脑点评

最适合移动办公的三款掌上电脑点评2020-03-31 16:35:554点赞22收藏25评论办公经常使用的是台式电脑或者常规的笔记本&#xff0c;笔记本因其体积较小且轻薄&#xff0c;更适合移动办公&#xff0c;但毕竟十几寸的体积&#xff0c;好几斤的重量&#xff0c;随身携带还是不便&…

正态分布的

正态分布&#xff08;台湾作常态分布&#xff0c;英语&#xff1a;normal distribution&#xff09;又名高斯分布&#xff08;英语&#xff1a;Gaussian distribution&#xff09;&#xff0c;是一个非常常见的连续概率分布。正态分布在统计学上十分重要&#xff0c;经常用在自…

rest spring_Spring REST:异常处理卷。 2

rest spring这是有关使用Spring进行REST异常处理的系列的第二篇文章。 在我以前的文章中&#xff0c;我描述了如何在REST服务中组织最简单的异常处理。 这次&#xff0c;我将更进一步&#xff0c;并向您展示何时最好在ControllerAdvice级别上使用异常处理 。 介绍 在开始本文…

计算机屏幕抖动怎么办,win7屏幕抖动怎么办_win7显示器屏幕抖动的解决方法

电脑使用久了之后难免会出现一些问题&#xff0c;近日就有网友反映说自己的win7旗舰版电脑出现了显示器屏幕抖动的情况&#xff0c;不知道怎么处理这一问题&#xff0c;没关系&#xff0c;下面小编就来为大家分享关于win7显示器屏幕抖动的解决方法。解决方法如下&#xff1a;方…