【数据结构-图】1.图的构造和遍历(基本理论+代码)

2023-10-27

一、图的基本概念

图: 图G是一个有序二元组(V,E),其中V称为顶集(Vertices Set),E称为边集(Edges set),E与V不相交。它们亦可写成V(G)和E(G)。其中,顶集的元素被称为顶点(Vertex),边集的元素被称为边(edge)。

有向图: 若E是有向边(也称弧)的有限集合时,则图G为有向图。弧是顶点的有序对,记为 < v , w > <v,w> <v,w> ,称为从顶点v到顶点w的弧。如上图中(a): G 1 = ( V 1 , E 1 ) ∣ ∣ V 1 = { 1 , 2 , 3 } ∣ ∣ E 1 = { < 1 , 2 > , < 2 , 1 > , < 2 , 3 > } G_1=(V_1,E_1)||V_1=\{1,2,3\}||E_1=\{<1,2>,<2,1>,<2,3>\} G1=(V1,E1)V1={1,2,3}E1={<1,2>,<2,1>,<2,3>}

无向图: 若E是无向边(简称边)的有限集合时,则图G为无向图。边是顶点的无序对,记为 < v , w > <v,w> <v,w> ,称为从顶点v和顶点w的互为邻接点。如上图中(b): G 1 = ( V 1 , E 1 ) ∣ ∣ V 1 = { 1 , 2 , 3 , 4 } ∣ ∣ E 1 = { ( 1 , 2 ) , ( 1 , 3 ) , ( 1 , 4 ) , ( 2 , 3 ) , ( 2 , 4 ) , ( 3 , 4 ) ) } G_1=(V_1,E_1)||V_1=\{1,2,3,4\}||E_1=\{(1,2),(1,3),(1,4),(2,3),(2,4),(3,4))\} G1=(V1,E1)V1={1,2,3,4}E1={(1,2),(1,3),(1,4),(2,3),(2,4),(3,4))}

简单图: 一个图满足:① 不存在重复边;② 不存在顶点到自身的边,则称图G为简单图。数据结构中只讨论简单图,如图a,b,c

多重图: 不满足简单图中两个条件,则称为多重图。

完全图: 在无向图中,若任意两个顶点之间都存在边,则称该图为无向完全图。拥有n个顶点的无向完全图有 n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n1) 条边,如图b

子图: 设有两个图 G = ( V , E ) G=(V,E) G=(V,E) G 1 = ( V 1 , E 1 ) G_1=(V_1,E_1) G1=(V1,E1) ,若 V 1 V_1 V1 V V V 的子集,且 E 1 E_1 E1 E E E 的子集,则称 G 1 G_1 G1 G G G 的子图。如图a和c

连通: 若从顶点v到顶点w有路径存在,则称v和w是连通的

连通图: 若图 G G G 中任意两个顶点都是连通的,则称图 G G G 为连通图,否则称为非连通图

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

极大连通子图

  1. 连通图只有一个极大连通子图,就是它本身。(是唯一的)

  2. 非连通图有多个极大连通子图。(非连通图的极大连通子图叫做连通分量,每个分量都是一个连通图

  3. 称为极大是因为如果此时加入任何一个不在图的点集中的点都会导致它不再连通。

    下图为非连通图,图中有两个极大连通子图(连通分量)。

在这里插入图片描述

极小连通子图

  1. 一个连通图的生成树是该连通图顶点集确定的极小连通子图。(同一个连通图可以有不同的生成树,所以生成树不是唯一的)
    (极小连通子图只存在于连通图中)

  2. 用边把极小连通子图中所有节点给连起来,若有n个节点,则有n-1条边。如下图生成树有6个节点,有5条边。

  3. 之所以称为极小是因为此时如果删除一条边,就无法构成生成树,也就是说给极小连通子图的每个边都是不可少的。

  4. 如果在生成树上添加一条边,一定会构成一个环。

    也就是说只要能连通图的所有顶点而又不产生回路的任何子图都是它的生成树。

在这里插入图片描述

总结来说:极大连通子图是讨论连通分量的,极小连通子图是讨论生成树的。

强连通图: 有向图 G G G 中, 若对于 V ( G ) V(G) V(G) 中任意两个不同的顶点 v i v_i vi v j v_j vj ,都存在从 v i v_i vi v j v_j vj 以及从 v j v_j vj v i v_i vi 的路径,则称图 G G G 是强连通图。如图c

强连通分量: 有向图的极大强连通子图称为 G G G 的强连通分量,强连通图只有一个强连通分量,即是其自身。非强连通的有向图有多个强连通分量。

生成树: 连通图的生成树是包含图中所有顶点的一个极小连通子图。若图中有n个点,那么生成树含有n-1条边,无论消去哪条边,整个图就不再连通;而无论在哪两个顶点加上一条边,都会形成回路

生成森林: 在非连通图中,连通分量的生成树构成了非连通图的生成森林。

顶点的度:(无向图)该顶点为一个端点的边的数目,记为 T D ( v ) TD(v) TD(v)。度与边之比为 2 e : e 2e:e 2e:e

顶点的入度:(有向图)以顶点v的为终点的有向边的数目 I D ( v ) ID(v) ID(v)

顶点的出度:(有向图)以顶点v的为起点的有向边的数目 O D ( v ) OD(v) OD(v)

边的权和网: 在一个图中,每条边都可以标上具有某种含义的数值,该数值称为该边的权值;这种边上带有权值的图称为带权图,也称为网

稠密图: 边数很多的图。一般满足 E ≥ V l o g V E≥VlogV EVlogV 的图称为稀疏图

稀疏图: 边数很少的图。一般满足 E < V l o g V E<VlogV E<VlogV 的图称为稀疏图

路径: 顶点 V p V_p Vp 到顶点 V q V_q Vq 之间的一条路径是指顶点序列 V p V_p Vp V i 1 V_{i1} Vi1 V i 2 V_{i2} Vi2 ,…, V m V_m Vm V p V_p Vp

路径长度: 路径上边的数目

回路: 第一个顶点和最后一个顶点相同的路径

简单路径: 顶点不重复出现的路径

简单回路: 除第一个顶点和最后一个顶点外,其余顶点不重复出现的回路

距离: 从顶点 V 1 V_1 V1 到顶点 V 2 V_2 V2 的最短路径若存在,则此路径的长度称为从顶点 V 1 V_1 V1 到顶点 V 2 V_2 V2 的距离

有向树: 一个顶点的入度为0、其余顶点的入度均为1

二、图的构造
2.1 构造邻接矩阵

不带权图:
A [ i ] [ j ] = { 1 , 若 ( V 1 , V 2 ) 或 < V 1 , V 2 > 是图中的边 0 , 若 ( V 1 , V 2 ) 或 < V 1 , V 2 > 不是图中的边 A[i][j]= \begin{cases} 1, & \text {若$(V_1,V_2)$或$ <V_1,V_2> $是图中的边}\\ 0, & \text {若$(V_1,V_2)$或$ <V_1,V_2> $不是图中的边} \end{cases} A[i][j]={1,0,(V1,V2)<V1,V2>是图中的边(V1,V2)<V1,V2>不是图中的边
带权图:
A [ i ] [ j ] = { W i j , 若 ( V 1 , V 2 ) 或 < V 1 , V 2 > 是图中的边 0 或 ∞ , 若 ( V 1 , V 2 ) 或 < V 1 , V 2 > 不是图中的边 A[i][j]= \begin{cases} W_{ij}, & \text {若$(V_1,V_2)$或$ <V_1,V_2> $是图中的边}\\ 0或∞, & \text {若$(V_1,V_2)$或$ <V_1,V_2> $不是图中的边} \end{cases} A[i][j]={Wij,0,(V1,V2)<V1,V2>是图中的边(V1,V2)<V1,V2>不是图中的边



#include <stdio.h>
int main() {
	const int MAX_N = 5; // 一共有五个顶点 
	int G[MAX_N][MAX_N] = {};	// 使用邻接矩阵表示
	G[0][2] = 1; 	// 将图连通且不带权
	G[0][4] = 1; 
	G[1][0] = 1; 
	G[1][2] = 1; 
	G[2][3] = 1; 
	G[3][4] = 1;
	G[4][3] = 1;
	printf("G:\n");
	for(int i=0; i<5; i++) {
        for(int j=0; j<5; j++) {
            printf("%d",G[i][j]);
        }
        printf("\n"); 
	}
	return 0;
} 

注意:

  1. 在简单应用中,可直接用二维数组作为图的邻接矩阵
  2. 无向图的邻接矩阵是对称矩阵,对规模特大的邻接矩阵可采用压缩存储。
  3. 邻接矩阵表示法的空间复杂度为 O ( n 2 ) O(n^2) O(n2),其中n为图的顶点数。

图的邻接矩阵存储表示法具有以下特点∶

  1. 无向图的邻接矩阵一定是一个对称矩阵(并且唯一)。因此,在实际存储邻接矩阵时只需存储上(或下)三角矩阵的元素.
  2. 对于无向图,邻接矩阵的第 i 行(或第 i 列)非零元素的个数态好是第 i 个顶点的度 TD(v)
  3. 对于有向图,邻接矩阵的第i行(或第i列)非零元素(或非四元素)的参正好是第i个顶点的出度 OD(v)(或入度ID(v)
  4. 用邻接矩阵法存储图,很容易确定图中任意两个顶点之间是否有边相差。但是,要确定图中有多少条边,则必须按行、按列对每个元素进行检测,所花费的时间代价很大。这是用邻接矩阵存储图的局限性。
  5. 密图适合使用邻接矩阵的存储表示。
  6. 设图G的邻接矩阵为A, A n A^n An的元素 A n [ i ] [ j ] A^n[i][j] An[i][j] 等于由顶点 i 到顶点 j 的长度为n的路径的数
目。
2.2 邻接表

我觉得图比问题更容易理解事物本质,所以简单讲一下概念,直接上图。

所谓邻接表,是指对图 G中的每个顶点v建立一个单链表,第 i 个单链表中的结点表示依附于顶点 v 的边(对于有向图则是以顶点v为尾的弧),这个单链表就称为顶点v的边表(对于有向图则称为出边表)。



#include <stdio.h>
#include <vector>
using namespace std;

struct GNode{
	int val;
	vector<GNode*> neighbors;
	GNode(int x):val(x) {
	}
}; 

int main() {
	int MAX_N = 5; // 五个节点
	GNode *Node[MAX_N];
	for(int i = 0; i < MAX_N; i++) {
		Node[i] = new GNode(i);
	}
	Node[0]->neighbors.push_back(Node[2]);
	Node[0]->neighbors.push_back(Node[4]);
	Node[1]->neighbors.push_back(Node[0]);
	Node[1]->neighbors.push_back(Node[2]);
	Node[2]->neighbors.push_back(Node[3]);
	Node[3]->neighbors.push_back(Node[4]);
	Node[4]->neighbors.push_back(Node[3]);
	printf("Node:\n");
	for(int i = 0; i < MAX_N; i++) {
		printf("Node[%d]:",i);
		for(int j = 0; j < Node[i]->neighbors.size(); j++) {
			printf("%d ",Node[i]->neighbors[j]->val);
		}
		printf("\n");
	}
	for (int i = 0; i < MAX_N; i++) {
		delete Node[i];
	}
	return 0;
}

图的邻接表存储方法具有以下特点∶

  1. 若G为无向图,则所需的存储空间为 O ( V + 2 E ) O(V+2E) O(V+2E) ;若G为有向图,则所需的存储空间为 O ( V + E ) O(V+E) O(V+E) 。前者的倍数2是由于无向图中,每条边在邻接表中出现了两次。
  2. 对于稀疏图,采用邻接表表示将极大地节省存储空间。
  3. 在邻接表中,给定一顶点,能很容易地找出它的所有邻边,因为只需要读取它的邻接表。
在邻接矩阵中,相同的操作则需要扫描一行,花费的时间为 O(n)。但是,若要确定给定的两个顶点间是否存在边,则在邻接矩阵中可以立刻查到,而在邻接表中则需要在相应结点对应的边表中查找另一结点,效率较低。
  4. 在有向图的邻接表表示中,求一个给定顶点的出度只需计算其邻接表中的结点个数;但
求其顶点的入度则需要遍历全部的邻接表。因此,也有人采用逆邻接表的存储方式来加速求解给定顶点的入度。当然,这实际上与邻接表存储方式是类似的。
  5. 图的邻接表表示并不唯一,因为在每个顶点对应的单链表中,各边结点的链接次序可以
是任意的,它取决于建立邻接表的算法及边的输入次序。
2.3 十字链表

十字链表是有向图的另一种链式存储结构。该结构可以看成是将有向图的邻接表和逆邻接表结合起来得到的。用十字链表来存储有向图,可以达到高效的存取效果。同时,代码的可读性也会得到提升。

在这里插入图片描述

顶点结点:

  1. data域:存放顶点相关的数据信息
  2. firstin域:以该结点为弧头(线段上有箭头的)
  3. firstout域:以该结点为弧尾(线段上无箭头的)


弧结点:

  1. tailvex:指示弧尾(线段上无箭头的)
  2. headvex:指示弧头(线段上有箭头的)
  3. hlink:弧头相同的下一条弧
  4. tlink:弧尾相同的下一条弧
  5. info:指向该弧的相关信息


十字链表存储结构:

typedef struct ArcBox   // 弧的结构表示
{
    int tailvex, headvex;
    InfoType  *info;
    struct ArcBox  *hlink, *tlink;
} VexNode;
typedef struct VexNode   // 顶点的结构表示
{
    VertexType  data;
    ArcBox  *firstin, *firstout;
} VexNode;
typedef struct
{
    VexNode  xlist[MAX_VERTEX_NUM];// 顶点结点(表头向量)
    int   vexnum, arcnum;//有向图的当前顶点数和弧数
} OLGraph;

对于十字链表的一些认识:

  1. 表头结点即顶点结点,与邻接表一样是顺序存储。

  2. 对于每个顶点结点之后是与之相关联的弧结点(该弧结点中存有弧头、弧尾),而邻接表则是一些与顶点结点相连接的点。

  3. 从每个顶点结点开始有两条链表,一条是以该顶点结点为弧头的链表,一条是以该顶点结点为弧尾的链表。

  4. 对于其中的每一条链表必然是从顶点结点开始,直到与之相关的弧结点链域headlink和taillink为空是结束,构成一条完整的链表。

2.4 链表多重表

邻接多重表存储无向图的方式,可看作是邻接表和十字链表的结合。同邻接表和十字链表存储图的方法相同,都是独自为图中各顶点建立一张链表,存储各顶点的节点作为各链表的首元节点,同时为了便于管理将各个首元节点存储到一个数组中。

邻接多重表各结点的结构示意图,如下图所示:



data:存储此顶点的数据;

firstedge:指针域,用于指向同该顶点有直接关联的存储其他顶点的节点。

各链表中其他节点的结构与十字链表中相同,如下图所示:



mark:标志域,用于标记此节点是否被操作过,例如在对图中顶点做遍历操作时,为了防止多次操作同一节点,mark 域为 0 表示还未被遍历;mark 为 1 表示该节点已被遍历;

ivex 和 jvex:数据域,分别存储图中各边两端的顶点所在数组中的位置下标;

ilink:指针域,指向下一个存储与 ivex 有直接关联顶点的节点;

jlink:指针域,指向下一个存储与 jvex 有直接关联顶点的节点;

info:指针域,用于存储与该顶点有关的其他信息,比如无向网中各边的权;

无向图的邻接多重表表示,如下图所示:



#define MAX_VERTEX_NUM 20                   //图中顶点的最大个数
#define InfoType int                        //边含有的信息域的数据类型
#define VertexType int                      //图顶点的数据类型
typedef enum {unvisited,visited}VisitIf;    //边标志域
typedef struct EBox{
    VisitIf mark;                           //标志域
    int ivex,jvex;                          //边两边顶点在数组中的位置下标
    struct EBox * ilink,*jlink;             //分别指向与ivex、jvex相关的下一个边
    InfoType *info;                         //边包含的其它的信息域的指针
}EBox;
typedef struct VexBox{
    VertexType data;                        //顶点数据域
    EBox * firstedge;                       //顶点相关的第一条边的指针域
}VexBox;
typedef struct {
    VexBox adjmulist[MAX_VERTEX_NUM];//存储图中顶点的数组
    int vexnum,degenum;//记录途中顶点个数和边个数的变量
}AMLGraph;
三、图的遍历
3.1 图的深度优先遍历


  1. 从图中某个顶点v出发,首先访问该顶点
  2. 然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图
  3. 直至图中所有和v有路径相通且未被访问的顶点都被访问到。
  4. 若此时尚有其他顶点未被访问到
  5. 则另选一个未被访问的顶点作起始点,
  6. 重复上述过程,直至图中所有顶点都被访问到为止。
#include <stdio.h>
#include <vector>
using namespace std;

struct GNode{
	int val;
	vector<GNode*> neighbors;
	GNode(int x):val(x){
	}
};

void DFSGraph(GNode *node, int visit[]) {
	visit[node->val] = 1;	// 标记已访问的顶点
	printf("%d ",node->val);
	for(int i = 0; i < node->neighbors.size(); i++) {
        if(visit[node->neighbors[i]->val] == 0) {
            DFSGraph(node->neighbors[i], visit);
        }
	} 
}

int main() {
	int MAX_N = 5;
	GNode *Node[MAX_N];
	for(int i = 0; i < MAX_N; i++) {
		Node[i] = new GNode(i);
	}
	Node[0]->neighbors.push_back(Node[2]);
	Node[0]->neighbors.push_back(Node[4]);
	Node[1]->neighbors.push_back(Node[0]);
	Node[1]->neighbors.push_back(Node[2]);
	Node[2]->neighbors.push_back(Node[3]);
	Node[3]->neighbors.push_back(Node[4]);
	Node[4]->neighbors.push_back(Node[3]);
	int visit[MAX_N] = {0};
	for(int i = 0; i < MAX_N; i++) {
        if(visit[i] == 0) { // 没有标记的顶点才会被访问 
            printf("From val(%d): ", Node[i]->val);
            DFSGraph(Node[i], visit);
            printf("\n");
        }
	}
	for (int i = 0; i < MAX_N; i++) {
        delete Node[i];
	}
	return 0;
}

时间复杂度:以邻接矩阵为例,查找每个顶点的邻接点所需的时间为 O ( ∣ V ∣ ) O(|V|) O(V),故总的时间复杂度为 O ( ∣ V ∣ 2 ) O(|V|^2) O(V2);以邻接表为例,查找所有顶点的邻接点所需的时间为 O ( ∣ E ∣ ) O(|E|) O(E) ,访问顶点所需的时间为 O ( ∣ V ∣ ) O(|V|) O(V),故总的时间复杂度为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(V+E)

空间复杂度:需要一个递归栈, O ( ∣ V ∣ ) O(|V|) O(V)

3.2 图的广度优先遍历


  1. 从图中某个顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,
  2. 然后分别从这些邻接点出发依次访问它们的邻接点,
  3. 并使得"先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问",
  4. 直至图中所有已被访问的顶点的邻接点都被访问到。
  5. 如果此时图中尚有顶点未被访问,
  6. 则需要另选一个未曾被访问过的顶点作为新的起始点,
  7. 重复上述过程,直至图中所有顶点都被访问到为止。
#include <stdio.h>
#include <vector>
#include <queue> 
using namespace std;

struct GNode{
	int val;
	vector<GNode*> neighbors;
	GNode(int x):val(x){
	}
};

void BFSGraph(GNode *node, int visit[]) {
	queue<GNode*> q;	// 广度优先搜索使用队列 
	q.push(node);
	visit[node->val] = 1;	// 标记已访问的顶点
	while(!q.empty()){
		GNode *temp = q.front();
		q.pop();
		printf("%d ",temp->val);
		for(int i = 0; i < temp->neighbors.size(); i++) {
			if(visit[temp->neighbors[i]->val] == 0) {
				q.push(temp->neighbors[i]);
				visit[temp->neighbors[i]->val] = 1;
			}
		} 
	} 

}

int main() {
	int MAX_N = 5;
	GNode *Node[MAX_N];
	for(int i = 0; i < MAX_N; i++) {
		Node[i] = new GNode(i);
	}
	Node[0]->neighbors.push_back(Node[2]);
	Node[0]->neighbors.push_back(Node[4]);
	Node[1]->neighbors.push_back(Node[0]);
	Node[1]->neighbors.push_back(Node[2]);
	Node[2]->neighbors.push_back(Node[3]);
	Node[3]->neighbors.push_back(Node[4]);
	Node[4]->neighbors.push_back(Node[3]);
	int visit[MAX_N] = {0};
	for(int i = 0; i < MAX_N; i++) {
		if(visit[i] == 0) { // 没有标记的顶点才会被访问 
			printf("From val(%d): ", Node[i]->val);
			BFSGraph(Node[i], visit);
			printf("\n");
		}
	}
	for (int i = 0; i < MAX_N; i++) {
		delete Node[i];
	}
	return 0;
}

时间复杂度:以邻接矩阵为例,查找每个顶点的邻接点所需的时间为 O ( ∣ V ∣ ) O(|V|) O(V),故总的时间复杂度为 O ( ∣ V ∣ 2 ) O(|V|^2) O(V2);以邻接表为例,在任意顶点的邻接表,每条边至少访问一次,此时时间复杂度为 O ( ∣ E ∣ ) O(|E|) O(E) ,另外,每个顶点均需搜索一次,此时时间复杂度为 O ( ∣ V ∣ ) O(|V|) O(V),故总的时间复杂度为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(V+E)

空间复杂度:需要一个辅助队列Q,最坏的情况下,空间复杂度为 O ( ∣ V ∣ ) O(|V|) O(V)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【数据结构-图】1.图的构造和遍历(基本理论+代码) 的相关文章

  • 1399: 最小生成树

    题目描述 最小生成树问题是实际生产生活中十分重要的一类问题 假设需要在n个城市之间建立通信联络网 则连通n个城市只需要n 1条线路 这时 自然需要考虑这样一个问题 即如何在最节省经费的前提下建立这个通信网 可以用连通网来表示n个城市以及n个
  • C#编程——List泛型集合

    文章目录 一 属性方法 常用 二 需求实例 三 微软官方 List lt T gt 地址截图 一 属性方法 常用 二 需求实例 目录 栏有15个按钮 红色 对应15个视频 黄色 点击序号为奇数的按钮 相应的视频出现在第一个窗口 点击 序号为
  • 数据结构:KMP算法

    给定一个字符串 S 以及一个模式串 P 所有字符串中只包含大小写英文字母以及阿拉伯数字 模式串 P 在字符串 S 中多次作为子串出现 求出模式串 P 在字符串 S 中所有出现的位置的起始下标 KMP算法 数组下标从1开始 额外next数组
  • java-统计一段句子中各单词出现的次数

    问题 统计一段句子中各单词出现的次数 思路 1 使用split方法将文章进行分割 我们这里以空格 逗号和句点为分隔符 然后存到一个字符串数组中 2 创建一个hashMap集合 key是字符串类型 保存单词 value是数字类型 保存该单词出
  • 设计一算法,将已建立的单链表进行逆置

    单链表逆序有很多种方法 可是好多种方法都是逆序后就不能再使用之前定义的函数了 因为你的头结点变动了 不再是之前所定义的first或是head了 所以之前的方法都要重写 后来我终于想到了种很好的方法了 为了不重开空间 我们可以就在原来的那个单
  • 模拟实现string类

    namespace zwj class string public 迭代器 typedef char iterator typedef const char const iterator 迭代器 iterator begin return
  • 数据结构之图:无向图的介绍与功能实现,Python——22

    无向图 Undigraph 的介绍 引入 生活中的图 有地图 集成电路板的图 可以看类似的看做是数据结构中的图 数据有 一对一 一对多 和 多对多 的关系 前两种分别表示线性表和树的存储结构性质 而多对多则可表示图的存储结构性质 定义 图是
  • 图的常用遍历——广度优先遍历和深度优先遍历

    目录 一 遍历图可能遇到的问题 二 图的常用遍历 三 深度优先遍历 DFS 四 广度优先遍历 BFS 一 遍历图可能遇到的问题 图的特点 图中可能存在回路 且图的任一顶点都可能与其它顶点相通 在访问完某个顶点之后可能会沿着某些边又回到了曾经
  • 数据结构课程设计c语言运动会管理系统

    参加运动会的有n个学院 学校编号为1 n 比赛分成m个男子项目 和w个女子项目 项目编号为男子1 m 女子m 1 m w 不同的项目取前八名积分 且前八名的积分分别为 9 7 6 5 4 3 2 1 m lt 20 n lt 20 功能要求
  • 使用阿里云日志服务来分析日志

    随着云服务技术越来越成熟 作为一枚运维 不得不感慨云计算的发展对我的职业生涯起了积极推动的作用 一方面我可以通过云服务来提高我的工作效率 另一方面我节省了更多时间来学习 在提高我专业度的同时 个人能力也越来越强 在此我就以阿里云日志服务 给
  • 弗洛伊德算法(floyd)

    弗洛伊德算法和迪杰斯特拉算法都是求两点之间最短路径的问题 弗洛伊德算法使用了动态规划的思想 用二维矩阵记录了所有点之间最短的距离 虽然代码只有几行 但是思想还很值得回味的 其主要的思想就是两个点之间的直接距离能否使用第三个点来缩短 公式 v
  • C++二叉树遍历总结\100. Same Tree

    理论学习 概念介绍 遍历图解 遍历算法 代码实践 实现模板 Same Tree 题目描述 代码实现 转载请注明出处 http blog csdn net c602273091 article details 55195284 理论学习 概念
  • EXCEL-VBA:递归遍历文件夹及子文件夹中的文件

    Const SearchPath D PDF Dim DicList FileList I FileName FilePath Set DicList CreateObject Scripting Dictionary Set FileLi
  • 【知识分享】数据结构的应用——链表

    背景 对于数据结构 其实学过C语言的都不陌生 无外乎就队列 栈 二叉树等等这些 但其实对于初学者最困惑的不是数据结构是怎么样的 而是数据结构有什么用 我自己也是工作好几年后才体验到数据结构的快乐 所以本系列文章重点从应用场景切入 让大家理解
  • 数据结构(2.1)——时间复杂度和空间复杂度计算

    前言 1 因为上一篇博客 数据结构 2 算法对于时间复杂度和空间复杂度计算的讲解太少 所以我在次增加多个案例讲解 2 上一篇已经详细介绍了 为什么我们的算法要使用复杂度这一个概念 因此 我这一篇将重点介绍 复杂度如何进行计算 时间复杂度计算
  • 算术表达式的前缀式、中缀式、后缀式相互转换

    中缀表达式 中缀记法 中缀表达式是一种通用的算术或逻辑公式表示方法 操作符以中缀形式处于操作数的中间 中缀表达式是人们常用的算术表示方法 虽然人的大脑很容易理解与分析中缀表达式 但对计算机来说中缀表达式却是很复杂的 因此计算表达式的值时 通
  • [leetcode] 827. 最大人工岛

    class Solution private int size 507 507 int fa 507 507 void init for int i 0 i lt n m i fa i i size i 1 int find int x i
  • 迪杰斯特拉算法(Dijkstra)-Java实现

    迪杰斯特拉算法也是求两点之间最短路径的算法 它的思想和普利姆算法有点相似 不断通过已找到点集合和未找到点之间的集合之间的最短路径 这个算法需要用到三个数组 一个是存储结点是否已经访问 一个是结点到起始点的最短距离 还有一个是结点到起始点第一
  • [LDUoj 倍增] 题解

    星星之火 可以燎原 细节的地方慢慢补充 欢迎提出问题 私聊 留言均可 A 跳跳棋 较难 B 聚会 板子题 C 祖孙询问 板子题 D Dis 板子题 E 次小生成树 严格次小生成树 难 F 异象石 难度适中 G 暗的连锁 难度适中 H 点的距
  • BFS遍历树和DFS遍历树

    遍历树 按照遍历的顺序 如不清楚图的遍历 请先阅读图的遍历 绘制成树型结构 DFS遍历树 以下为图到遍历树的转化 如果不清楚图的遍历 请先阅读笔者的另一篇文章 图的遍历 动图 按照DFS遍历的顺序 绘制成一棵树 途中红色的边就是遍历过程中没

随机推荐

  • 【毕设教程】深度学习经典网络 CNN模型:ResNet

    文章目录 0 简介 1 ResNet 介绍 2 深度网络的退化问题 3 残差学习 4 ResNet的网络结构 5 ResNet的TensorFlow实现 6 最后 0 简介 Hi 大家好 这里是丹成学长的毕设系列文章 对毕设有任何疑问都可以
  • HTML-CSS笔记_0424

    HTML CSS 学习笔记源码 链接 https pan baidu com s 1PRorRSlAW0PSHM4grOoapg 提取码 fnr2 HTML 一 网页的基本结构和基础 1 html基础
  • qt 实现UDP通信简单案例

    实现效果 实现功能 创建两个界面 可以通过udp进行通信 并显示通信内容 界面部分由代码实现 并使用qss简单美化 udp通信由创建套接字 绑定端口号 发送和接收数据函数完成 代码实现 创建第一个通信对象 ud1 h ifndef UDPU
  • 【CV学习笔记】onnx篇之DETR

    1 摘要 本次学习内容主要学习了DETR的网络结构 损失函数等知识 明白了DETR是如何做到了端到端的检测 确实是一个十分优雅的框架 同时将DETR利用onnxtime进行推理 对于transformer的理解进一步加深了 DETR学习链接
  • Vue中关于组件的封装复用

    我们在写前端代码时常常会有一些控件或者HMTL代码片段在许多页面都需要 并且内容几乎一样 只是数据的不同而已 此时 我们就可以把这些代码封装成组件 以供我们重复使用 组件化 是一种思想 解决对复杂问题简单化的思想 将我们的程序开发成一个个独
  • 【持续更新】近期C++开发Modbus通讯接口小结

    项目需求 对PLC上存储的数据进行读取 并转存到数据库 语言 C DDL 所需知识点 Socket通信 Modbus帧结构 C 中数据库的操作 多线程 Linux 项目进度拆解记录 不会做就是困难 管它简不简单 1 Socket通信 由于之
  • mysql 配置文件-----【MySQL][5.1][.ini][5] MySQL my-innodb-heavy-4G.ini

    开始配置信息 描述 4GB 内存 只有 InnoDB ACID 几个连接数 繁重的查询 类型 系统 结束配置信息 这是一个针对 4G 内存系统 主要运行只有 InnoDB 表的 MySQL 并使用几个连接数执行复杂的查询 的 MySQL 配
  • 大数据小细节、小经验

    1 把操作hive的sql写在sh脚本里 用 bin hive f 执行脚本 不用登陆hive命令行界面 这样可以脚本自动化执行某些任务 2 expect脚本 先安装expect插件 yum y install expect bin exp
  • python练习——实现质数检测,编写isprime()函数,参数为整数,并且需要有异常处理功能。

    编写isprime 函数 参数为整数 并且需要有异常处理功能 此函数的功能是检测接收的整数是否为质数 如果整数是质数 则返回True 否则返回False 编写isprime 函数 参数为整数 并且需要有异常处理功能 此函数的功能是检测接收的
  • C++入门练习题[1]:KiKi定义电子日历类

    最近在看C 入门的书籍 但是光看是不够的 需要一些练习将知识运用起来 牛客网上面有在线编程的题目 我选择了一些入门的题目作为练习 1 题目 这道题的题目如下 2 解题 题目是非常简单的 但是因为只是看过了一遍知识点 没有动手实践 所以看起来
  • [Python系列-7]:Python之人工智能 - 基本工具 -1- Time库

    作者主页 文火冰糖的硅基工坊 https blog csdn net HiWangWenBing 本文网址 https blog csdn net HiWangWenBing article details 119253059 目录 1 什
  • 瑞吉外卖【后台管理系统篇】

    瑞吉外卖 一 软件开发整体介绍 1 软件开发流程 2 角色分工 3 软件环境 二 瑞吉外卖项目介绍 1 项目介绍 2 技术选型 3 功能架构 三 开发环境搭建 1 数据库环境搭建 2 maven项目搭建 四 后台功能开发 1 员工管理 1
  • Matlab中条件语句-if, elseif, else使用

    目录 语法 说明 示例 使用 if elseif 和 else 指定条件 比较数组 测试数组的相等性 比较字符向量 测试值的不相等性 评估表达式中的多个条件 if elseif else是条件为 true 时执行语句 语法 if expre
  • java数组为什么可以迭代吗_另一个“只能迭代数组或java.lang.Iterable实例”的问题...

    我有这段代码返回java lang iterable错误 我知道我在哪里出错 但是我不知道该如何解决 这是代码 public class ManagementServiceHandler implements ManagementServi
  • opencv3/C++ 机器学习-决策树/DTrees

    决策树 Decision Tree 决策树 Decision Tree是一棵二叉树 每棵非叶子节点有两个子节点的树 可用于分类或回归问题 对于分类问题 形成分类树 每个叶节点都标有一个类标签 多个叶节点可能具有相同的标签 对于回归问题 形成
  • 数据库题目:用“连接查询”查找和problem_id为 1009 的题目属于同一个比赛的题目信息,结果按problem_id升序排序。

    目录 Q 查找和problem id为 1009 的题目属于同一个比赛的题目信息 结果按problem id升序排序 1 problem为题目表 problem表如下图 仅显示前几条 编辑 2 contest problem为比赛 题目关系
  • 在程序运行中,页表是动态的还是静态的?

    最近在学习操作系统相关知识 在学习虚拟内存技术时产生了一个疑问 操作系统会在进程需要的时候将位于硬盘的数据页换入到物理内存中 在物理内存不够用的情况下会发生页面置换 而置换的物理内存页面应该是随机的 换出未来一段时间不太可能使用的页面 这个
  • 共享虚拟主机和服务器,独享和共享虚拟主机区别

    独享和共享 独享虚拟主机 是指独享一部分服务器资源的虚拟主机 比如独享CPU 独享内存 独享带宽等 共享虚拟主机 是我们常见的普通虚拟主机 服务器资源 大家共享 包括CPU 内存 带宽等 独享虚拟主机由于独享资源 因此在使用时 更稳定 而共
  • ssm sqlSessionFactory创建失败

    Caused by org springframework beans factory BeanCreationException Error creating bean with name sqlSessionFactory define
  • 【数据结构-图】1.图的构造和遍历(基本理论+代码)

    一 图的基本概念 图 图G是一个有序二元组 V E 其中V称为顶集 Vertices Set E称为边集 Edges set E与V不相交 它们亦可写成V G 和E G 其中 顶集的元素被称为顶点 Vertex 边集的元素被称为边 edge