408数据结构-图的遍历 自学知识点整理

前置知识:图的存储与基本操作


图的遍历是指从图的某一顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点访问一次,且仅访问一次。因为树是一种特殊的图,所以树的遍历实际上也可以视为一种特殊的图的遍历。图的遍历算法是求解图的连通性问题、拓扑排序和求关键路径等算法的基础。
因为图的任意一个顶点都可能和其余的顶点相邻接,所以再访问过某个顶点后,又可能沿着某条路径搜索回到这个被访问过的结点。为了避免同一个顶点被访问多次,在遍历图的过程中,必须记下每个已访问过的顶点,可以设一个辅助数组 v i s i t e d [   ] visited[\ ] visited[ ]来标记顶点是否被访问过。图的遍历算法主要有两种:广度优先搜索深度优先搜索

广度优先搜索

知识点回顾:二叉树的层次遍历
对二叉树进行按层次的遍历,需要借助一个辅助队列实现,具体思想如下:
①首先将二叉树的根结点入队。
②若队列非空,则队头结点出队,并访问该结点。若该结点有左孩子,则将其左孩子入队;若该结点有右孩子,则将其右孩子入队。
③重复步骤②,直至队列为空。

广度优先搜索 B r e a d t h − F i r s t − S e a r c h ,   B F S Breadth-First-Search,\ BFS BreadthFirstSearch, BFS)类似于二叉树的层次遍历算法。基本思想是:首先访问起始顶点 v v v,接着从 v v v出发,依次访问 v v v的各个未访问过的邻接顶点 w 1 , w 2 , ⋯   , w i {{w}_{1}},{{w}_{2}},\cdots ,{{w}_{i}} w1,w2,,wi,然后依次访问 w 1 , w 2 , ⋯   , w i {{w}_{1}},{{w}_{2}},\cdots ,{{w}_{i}} w1,w2,,wi的所有未被访问过的邻接顶点;再从这些访问过的顶点出发,访问它们所有未被访问过的邻接顶点,依此类推,直至图中所有顶点都被访问过为止。若此时图中尚有顶点未被访问,则另选图中一个未被访问过的顶点作为起始点,再重复上述过程,直至图中所有顶点都被访问到为止。
D i j k s t r a Dijkstra Dijkstra单源最短路径算法和 P r i m Prim Prim最小生成树算法也应用了类似的思想。
对广度优先搜索遍历图的过程,换而言之,就是以 v v v为起始点,由近至远依次访问和 v v v有路径相通且路径长度为 1 , 2 , ⋯ 1,2,\cdots 1,2,的顶点。广度优先搜索是一种分层的查找过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有往回退的情况,因此它不是一个递归的算法。为了实现逐层的访问,算法必须借助一个辅助队列,以记忆正在访问的顶点的下一层的顶点。

代码实现

首先是预处理,包括结构体定义,基本操作函数等。因为邻接矩阵法写起来相对简单一些,所以我主要用邻接表法来写。

知识点回顾:图的邻接表存储表示法
知识点类比:二叉树的层次遍历

#define MaxVertexNum 810
typedef struct ArcNode {//边结点
	int adjvex;
	struct ArcNode* nextarc;
}ArcNode;
typedef struct VNode {//顶点表结点
	int data;
	ArcNode* firstarc;
}VNode,AdjList[MaxVertexNum];
typedef struct {
	AdjList vertices;//邻接表存储图
	int vexnum, arcnum;
}ALGraph;
bool Visited[MaxVertexNum];//辅助数组标记顶点是否被访问

typedef struct LinkNode {
	int Vertex;//图的顶点编号
	struct LinkNode* next;
}LinkNode;
typedef struct {
	LinkNode* front, * rear;//链队列
}LinkQueue;

void InitQueue(LinkQueue& Q) {
	LinkNode* p = (LinkNode*)malloc(sizeof(LinkNode*));
	p->Vertex = -1;
	p->next = NULL;
	Q.front = Q.rear = p;//初始化队列
	return;
}

bool Q_Is_Empty(LinkQueue Q) {//队列判空
	return Q.front == Q.rear ? true : false;
}

void EnQueue(LinkQueue& Q, int i) {//新元素入队
	LinkNode* p = (LinkNode*)malloc(sizeof(LinkNode*));
	p->Vertex = i;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
	return;
}

void DeQueue(LinkQueue& Q, int& x) {//队头元素出队
	LinkNode* p = Q.front->next;
	x = p->Vertex;
	Q.front->next = p->next;
	if (Q.rear == p)Q.rear = Q.front;
	free(p);
	return;
}

void Visit(int i) {
	printf("%d ", i);
	return;
}

邻接表实现广度优先搜索的代码如下:

void BFS(ALGraph& G, LinkQueue& Q, int i) {//广度优先搜索(对连通分量)
	Visit(i);//先访问i
	Visited[i] = true;
	EnQueue(Q, i);
	int v, w;//v记录队首元素,w用于临时记录访问的顶点
	while (!Q_Is_Empty(Q)) {//当队列不为空时
		DeQueue(Q, v);//队首元素出队
		for (ArcNode* p = G.vertices[v].firstarc; p != NULL; p = p->nextarc) {
		//访问v所有的邻接顶点
			w = p->adjvex;
			if (!Visited[w]) {//若顶点w未被访问过
				Visit(w);//访问顶点w
				Visited[w] = true;//对顶点w作已访问标记
				EnQueue(Q, w);//顶点w入队
			}
		}
	}
	return;
}

void BFSTraverse(ALGraph& G, LinkQueue& Q) {//对图G进行广度优先遍历
	for (int i = 1; i <= G.vexnum; ++i) {
		Visited[i] = false;//访问标记数组初始化
		G.vertices[i].data = i;//其实这一步没用
	}
	InitQueue(Q);//初始化队列
	for (int i = 1; i <= G.vexnum; ++i)//从1号顶点开始遍历
		if (!Visited[i])//对每个连通分量调用一次BFS()
			BFS(G, Q, i);//若顶点v_i未被访问过,则从顶点v_i处开始调用BFS()
	return;
}

邻接矩阵实现广度优先搜索算法如下:(并不完整,感兴趣的读者可以尝试自己写一下)

#define MaxVertexNum 114
typedef struct {
	int Vex[MaxVertexNum];
	int Edge[MaxVertexNum][MaxVertexNum];
	int vexnum, arcnum;
}MGraph;

void BFS_(MGraph& G, LinkQueue& Q, int i) {
	Visit(i);
	Visited[i] = true;
	EnQueue(Q, i);
	int v, w;
	while (!Q_Is_Empty(Q)) {
		DeQueue(Q, v);
		for (w = 1; w <= G.vexnum; ++w) {
			if (!Visited[w] && G.Edge[v][w]) {
				Visit(w);
				Visited[w] = true;
				EnQueue(Q, w);
			}
		}
	}
	return;
}

辅助数组 V i s i t e d [   ] Visited[\ ] Visited[ ]标志顶点是否被访问过,其初始值为 f a l s e false false。在图的遍历过程中,一旦某个顶点 v i v_i vi被访问,就立即置 V i s i t e d [ i ] Visited[i] Visited[i]值为 t r u e true true,防止其被多次访问。

B F S BFS BFS算法性能分析

无论是邻接表还是邻接矩阵的存储方式, B F S BFS BFS算法都需要借助一个辅助队列 Q Q Q,所有顶点均需入队一次,在最坏的情况下,空间复杂度为 O ( ∣ V ∣ ) O(|V|) O(V)
遍历图的过程实质上是对每个顶点查找其邻接点的过,耗费的时间取决于所采用的存储结构。
采用邻接表存储时,每个顶点均需入队一次,时间复杂度为 O ( ∣ V ∣ ) O(|V|) O(V),在搜索每个顶点的邻接点时,每条边至少访问一次,时间复杂度为 O ( ∣ E ∣ ) O(|E|) O(E)。因此,总的时间复杂度为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(V+E)
采用邻接矩阵存储时,查找每个顶点的邻接点所需时间为 O ( ∣ V ∣ ) O(|V|) O(V),因此,总的时间复杂度为 O ( ∣ V ∣ 2 ) O(|V|^{2}) O(V2)

B F S BFS BFS算法求解单源最短路径

若图 G = ( V , E ) G=(V,E) G=(V,E)为无权图,定义从顶点 u u u到顶点 v v v的最短路径 d ( u , v ) d(u,v) d(u,v) u u u v v v的任何路径中最少的边数;若从 u u u v v v没有通路,则 d ( u , v ) = ∞ d(u,v)=\infin d(u,v)=
使用 B F S BFS BFS,我们可以求解一个满足上述定义的“无权图的单源最短路径问题”,这是由广度优先搜索总是按照距离由近到远来遍历图中每个顶点的性质决定的。
B F S BFS BFS算法求解单源最短路径问题的算法如下,我根据王道书上的伪代码自己稍作了一些改动:

#define INF 0x7fffffff
void BFS_MIN_Distance(ALGraph G, LinkQueue& Q, int u) {
	int d[MaxVertexNum], v;//d[i]表示从u到i结点的最短路径
	memset(d, INF, sizeof(d));//初始化路径长度为无穷大
	Visited[u] = true, d[u] = 0;
	EnQueue(Q, u);
	while (!Q_Is_Empty(Q)) {//BFS主过程
		DeQueue(Q, u);//队头出队
		for (ArcNode* w = G.vertices[u].firstarc; w != NULL; w = w->nextarc) {
			//遍历u的所有邻接点
			v = w->adjvex;
			if (!Visited[v]) {//若未访问
				Visited[v] = true;//标记访问
				d[v] = d[u] + 1;//路径长度加1
				EnQueue(Q, v);//顶点w入队
			}
		}
	}
	return;
}
广搜的完整代码可以看我的Github:传送门

广度优先生成树

在广度优先遍历的过程中,我们可以得到一棵遍历树,称为广度优先生成树。需要注意的是,同一个图的邻接矩阵存储表示是唯一的,所以其广度优先生成树也是唯一的,但是因为邻接表存储表示不唯一,所以其广度优先生成树也不是唯一的。广度优先遍历序列同理,因此不再展开讲)

(下图来自王道考研408数据结构课程视频的截图 - 图的广度优先遍历)
图片来自王道考研408数据结构课程视频
对非连通图的广度优先遍历,可以得到广度优先生成森林。其中,对每一个连通分量进行广度优先遍历得到的广度优先生成树的集合,就是这个非连通图的广度优先生成森林。
这期视频最后的思考题,我个人认为答案如下:

  1. 1 1 1出发,需要调用 4 4 4 B F S BFS BFS函数,过程分别是: 1 → 5 1→5 15 2 2 2 3 → 6 3→6 36 4 → 7 → 8 4→7→8 478
  2. 7 7 7出发,需要调用 1 1 1 B F S BFS BFS函数,过程是: 7 → 3 → 6 → 8 → 2 → 4 → 1 → 5 7→3→6→8→2→4→1→5 73682415

深度优先搜索

知识点回顾:二叉树的先序遍历
若二叉树为空,则什么也不做;否则:

  • 访问根结点;
  • 先序遍历左子树;
  • 先序遍历右子树。

对应的递归算法如下:

void PreOrder(BiTree T) {//先序遍历(根左右)
	if (T != NULL) {
		visit(T);//访问根结点
		PreOrder(T->lchild);//递归访问左子树
		PreOrder(T->rchild);//递归访问右子树
	}
	return;
}

与广度优先搜索不同,深度优先搜索 D e p t h − F i r s t − S e a r c h Depth-First-Search DepthFirstSearch D F S DFS DFS)类似于树的先序遍历。如果其名称中所暗含的意思一样,这种搜索算法所遵循的策略是尽可能“深”地搜索一个图。
它的基本思想是:首先访问图中某一起始顶点 v v v,然后从 v v v出发,访问与 v v v邻接且未被访问的任意一个顶点 w 1 w_1 w1,再访问与 w 1 w_1 w1邻接且未被访问的任意一个顶点 w 2 w_2 w2……重复上述过程。当不能再继续往下访问时,依次退回到最近被访问的顶点,若它还有邻接顶点未被访问过,则再从该点开始继续上述搜索过程,直至图中所有顶点均被访问过为止。

代码实现

首先预处理,使用邻接表的方式存储图。

#define MaxVertexNum 114
typedef struct ArcNode {
	int adjvex;
	struct ArcNode* nextarc;
}ArcNode;
typedef struct VNode {
	int data;
	ArcNode* firstarc;
}VNode, AdjList[MaxVertexNum];
typedef struct {
	AdjList vertices;
	int vexnum, arcnum;
}ALGraph;

bool Visited[MaxVertexNum];//访问标记数组

inline void Visit(int i) {
	Visited[i] = true;//对i作已访问标记
	printf("%d ", i);
	return;
}

邻接表实现深度优先搜索算法如下:

inline void DFS(ALGraph G, int i) {//注:可以不加inline,仅个人习惯
	Visit(i);//访问初始顶点i
	for (ArcNode* p = G.vertices[i].firstarc; p != NULL; p = p->nextarc) {
	//检测i的所有邻接点
		int j = p->adjvex;
		if (!Visited[j])DFS(G, j);//若j未被访问,则递归访问j
	}
	return;
}

inline void DFSTraverse(ALGraph G) {
	for (int i = 1; i <= G.vexnum; ++i) {
		Visited[i] = false;//初始化访问标记数组
		G.vertices[i].data = i;
	}
	for (int i = 1; i <= G.vexnum; ++i) {//从1开始遍历
		if (!Visited[i])//若当前顶点未访问则调用DFS()
			DFS(G, i);
	}
	return;
}

这样写 D F S T r a v e r s e ( ) DFSTraverse() DFSTraverse()函数也能同时解决非连通图的遍历问题。
同样的,我也写了个不完整的邻接矩阵实现深度优先搜索算法,感兴趣的读者可以自己动手试试补全。

#define MaxVertexNum 114
typedef struct {
	int Vex[MaxVertexNum];
	int Edge[MaxVertexNum][MaxVertexNum];
	int vexnum, arcnum;
}MGraph;

inline void DFS_(MGraph G, int i) {
	Visit(i);//访问初始顶点i
	for (int j = 1; j <= G.vexnum; ++j) {
		//检查i的所有邻接点
		if (!Visited[j] && G.Edge[i][j])
			DFS_(G, j);//j为i尚未访问的邻接点,递归访问j
	}
	return;
}
深搜的完整代码可以看我的Github:传送门

D F S DFS DFS算法的性能分析

D F S DFS DFS是一个递归算法,主要空间复杂度来自递归函数工作栈,最坏情况下空间复杂度为 O ( ∣ V ∣ ) O(|V|) O(V)
遍历图的过程实质上是通过边查找邻接点的过程,因此两种遍历方式的时间复杂度都相同,不同之处仅在于对顶点的访问顺序不同。采用邻接矩阵存储时,总的时间复杂度为 O ( ∣ V ∣ 2 ) O(|V|^{2}) O(V2);采用邻接表存储时,总的时间复杂度为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(V+E)

深度优先生成树和生成森林

与广度优先搜索一样,深度优先搜索也会产生一棵深度优先生成树。当然,这是有条件的,即对连通图调用 D F S DFS DFS才能产生深度优先生成树,否则产生的将是深度优先生成森林
(下图来自王道考研408数据结构课程视频的截图 - 图的深度优先遍历)
图来自王道考研408数据结构课程视频
2 2 2出发,易知深度优先遍历序列为 2 → 1 → 5 → 6 → 3 → 4 → 7 → 8 2→1→5→6→3→4→7→8 21563478
图来自王道考研408数据结构课程视频
与广度优先搜索类似,邻接矩阵生成的深度优先序列和深度优先搜索树都是唯一的;而邻接表生成的深度优先序列和深度优先搜索树都是不唯一的,具体由邻接表边表的存储顺序决定。

图的遍历与图的连通性

图的遍历算法可以用来判断图的连通性。对于无向图来说,若无向图是连通的,则从任意一个顶点出发,仅需一次遍历就能够访问图中的所有顶点;若无向图是非连通的,则从某一个顶点出发,一次遍历只能访问到该顶点所在连通分量的所有顶点,而对于图中其他连通分量的顶点,则无法通过这次遍历访问到。对于有向图来说,若从初始顶点出发到图中的每个顶点都有路径,则能够访问到图中的所有顶点,否则不能访问到所有顶点。
因此,在 B F S T r a v e r s e ( ) BFSTraverse() BFSTraverse() D F S T r a v e r s e ( ) DFSTraverse() DFSTraverse()函数中,添加了第二个 f o r for for循环,用于多次选取初始点,继续进行遍历,防止出现一次无法遍历图中所有顶点的情况。对于无向图,上述两个函数调用 B F S ( G , i ) BFS(G,i) BFS(G,i) D F S ( G , i ) DFS(G,i) DFS(G,i)的次数,等于该图的连通分量数;而对于有向图则不是这样,因为一个连通的有向图分为强连通的和非强连通的,它的连通子图也分为强连通分量和非强连通分量,对非强连通分量一次调用 B F S ( G , i ) BFS(G,i) BFS(G,i) D F S ( G , i ) DFS(G,i) DFS(G,i)存在无法访问到该连通分量所有顶点的情况。

知识点回顾:图的基本概念


对图的遍历,408考研初试中经常在选择题里考察遍历序列和遍历生成树的问题,对代码要求不那么高。因此要结合课后习题,在充分理解概念和算法思想的基础上,重点掌握手推遍历序列的能力。
以上。

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

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

相关文章

【Apache Doris】Compaction 原理 | 实践全析

【Apache Doris】Compaction 原理 | 实践全析 一、Compaction 前文概要二、Compaction 版本策略三、Compaction 类型说明四、Compaction 工程实现五、Compaction 生产实践 作者 &#xff5c; 俞剑波 一、Compaction 前文概要 LSM-Tree 简介 LSM-Tree&#xff08; Log Structu…

为什么笔记本电脑触控板不工作?这里有你想要的答案和解决办法

序言 你的笔记本电脑触控板停止工作了吗?值得庆幸的是,这个令人沮丧的问题通常很容易解决。以下是笔记本电脑触控板问题的最常见原因和修复方法。 触控板被功能键禁用 大多数(如果不是全部的话)Windows笔记本电脑都将其中一个功能键用于禁用和启用笔记本电脑触控板。按键…

Type-C接口显示器:C口高效连接与无限可能 LDR

Type-C显示器C接口的未来&#xff1a;高效连接与无限可能 随着科技的飞速发展&#xff0c;我们的日常生活和工作中对于高效、便捷的连接方式的需求日益增加。在这样的背景下&#xff0c;Type-C接口显示器凭借其卓越的性能和广泛的兼容性&#xff0c;正逐渐崭露头角&#xff0c…

永磁同步直线电机(PMLSM)控制与仿真1-永磁同步直线电机数学模型

文章目录 1、引言2、永磁同步直线电机数学模型2.1 直线电机的结构和工作原理2.2 永磁同步直线电机系统干扰分析2.2.1 齿槽效应2.2.2 端部效应 2.3 永磁同步直线电机的结构2.4 永磁同步直线电机的数学模型2.4.1 ABC坐标系下 PMLSM 的数学模型2.4.2 dq坐标系下 PMLSM 的数学模型2…

推荐这两款非常良心的录屏和文字转语音工具,很是让人心动,不要错过

VPot FREE 吾爱大神制作的文字转音频工具&#xff0c;免费使用。 支持英语、韩语、法语、日语等语言&#xff0c;还是支持男声、女声和儿童声音。 支持将以导入文本的格式转换成音频&#xff0c;并保存为MP3、WAV等常见的音频格式。 VPot FREE提供智能断句的功能&#xff0…

孝子黄香与颍川□董超

“香九龄&#xff0c;能温席&#xff0c;孝于亲&#xff0c;所当执。”家喻户晓、妇孺皆知的《三字经》让孝子黄香名扬千秋&#xff0c;成为“二十四孝”中闻名于世的“扇枕温衾”故事的主角。 黄香&#xff08;公元68—122年&#xff09;&#xff0c;字文强&#xff0c;东汉江…

谷歌上架,APP被移除了,没封号,换个包名还能重新提审上架?

对于在Google Play上架应用的开发者来说&#xff0c;尤其是那些矩阵式上架马甲包的开发者&#xff0c;可能已经遭遇过无数次应用被暂停或移除的情况了。通常这种情况下&#xff0c;账号也随之会被封&#xff0c;且大多数开发者认为&#xff0c;没有立马收到封号邮件的话&#x…

什么是深拷贝;深拷贝和浅拷贝有什么区别;深拷贝和浅拷贝有哪些方法(详解)

目录 一、为什么要区别深拷贝和浅拷贝 二、浅拷贝 2.1、什么是浅拷贝 2.2、浅拷贝的方法 使用Object.assign() 使用展开运算符(...) 使用数组的slice()方法&#xff08;仅适用于数组&#xff09; 2.3、关于赋值运算符&#xff08;&#xff09; 三、深拷贝 3.1、什么是…

CMU最新论文:机器人智慧流畅的躲避障碍物论文详细讲解

CMU华人博士生Tairan He最新论文&#xff1a;Agile But Safe: Learning Collision-Free High-Speed Legged Locomotion 代码开源&#xff1a;Code: https://github.com/LeCAR-Lab/ABS B站实际效果展示视频地址&#xff1a;bilibili效果地址 我会详细解读论文的内容,让我们开始吧…

大模型应用:LangChain-Golang核心模块使用

1.简介 LangChain是一个开源的框架&#xff0c;它提供了构建基于大模型的AI应用所需的模块和工具。它可以帮助开发者轻松地与大型语言模型(LLM)集成&#xff0c;实现文本生成、问答、翻译、对话等任务。LangChain的出现大大降低了AI应用开发的门槛&#xff0c;使得任何人都可以…

C++ UML建模

starUML UML图转C代码 数据流图 E-R图 流程图 整体架构图 ORM关系图 参考 app.asar附件资源可免激活 JHBlog/设计模式/设计模式/1、StarUML使用简明教程.md at master SunshineBrother/JHBlog GitHub C程序员UML实务手册代码 - 开发实例、源码下载 - 好例子网 GitHub -…

RK3568平台(触摸篇)触摸屏基本原理

一.触摸屏概述 触摸屏作为一种新的输入设备&#xff0c;它是目前最简单、方便、自然的一种人机交互方式。 触摸屏又称为“触控屏”、“触控面板”&#xff0c;是一种可接收触头等输入讯号的感应式液晶显示装置&#xff1b;当接触了屏幕上的图形按钮时&#xff0c;屏幕上的触觉…

python保存文件后打不开的原因是什么

引入数据集&#xff0c;奇怪的是怎么也打不开&#xff0c;显示不存在这个文件&#xff1a; 但是&#xff0c;我将文件改个名字&#xff0c;就打开了&#xff0c;难道csv的文件命名必须有一定合法性&#xff1f; import pandas users pandas.read_csv("H:\python\data an…

MySQL基础——函数和约束

目录 1函数 1.1字符串函数 1.2数值函数 1.3日期函数 1.4流程函数 2约束 2.1约束概述和演示 2.2外键约束&#xff08;表连接键&#xff09; 1函数 函数是指一段可以直接被另一段程序调用的程序或代码。 1.1字符串函数 MySQL中内置了很多字符串函数&#xff0c;常用的…

PCtoLCD2002 图片取模教程

记录一下取模软件&#xff0c;自己也是经常忘记怎么用&#xff0c;比较烦 按照下面这张图来就可以了&#xff0c;STM32的OLED屏幕可以直接用来显示图片。

VisionOS的未来愿景:苹果VisionPro创业者的愿望清单

随着苹果公司在增强现实(AR)领域的不断探索,VisionPro作为其前沿产品,已经开始展现出改变我们与数字世界互动方式的潜力。作为一名VisionPro创业者,对未来VisionOS的更新充满了期待,并提出了一系列愿望清单,这些愿望不仅代表了个人的需求,也反映了用户社区对苹果AR生态的…

算法设计与分析 实验2 分治法求最近点对

目录 一、实验目的 二、实验概述 一、实验目的 掌握分治法思想。学会最近点对问题求解方法。 二、实验概述 分治法也称为分解法、分治策略等。分治法算法思想如下&#xff1a; (1) 将一个问题划分为同一类型的若干子问题&#xff0c;子问题最好规模相同。 (2) 对这些子问题…

微信监控销售防飞单系统,让你的团队业绩稳如泰山!

团队中偶尔出现的私单、飞单问题而烦恼不已&#xff1f;你是否渴望拥有一个神器&#xff0c;能够实时监控销售过程&#xff0c;确保团队业绩的稳健增长&#xff1f;今天&#xff0c;就让我们一起探索这款神奇的“微信监控销售防飞单系统”&#xff0c;让你的销售团队如虎添翼&a…

scrapy爬取豆瓣书单存入MongoDB数据库

scrapy爬取豆瓣书单存入MongoDB数据库 一、安装scrapy库二、创建scrapy项目三、创建爬虫四、修改settings,设置UA,开启管道五、使用xpath解析数据六、完善items.py七、在douban.py中导入DoubanshudanItem类八、爬取所有页面数据九、管道中存入数据,保存至csv文件十、将数据写…

永磁同步直线电机(PMLSM)控制与仿真4-永磁同步直线电机数学三环闭环控制仿真

文章目录 1、参数设置及脚本2、相电流波形3、位置波形4、速度波形5、控制电流波形6、永磁同步直线电机在实际控制中如何控制参考 写在前面&#xff1a;原本为一篇文章写完了永磁同步直线电机数学模型介绍&#xff0c;永磁同步直线电机数学模型搭建&#xff0c;以及永磁同步直线…