无向图的遍历-BFS与DFS

2023-11-15

一,理论部分

无向图的遍历可用深度搜索(DFS)与广度搜索(BFS)

深度搜索的基本方式是由图的一个节点1出发然后随机选一个与其相邻的节点2,接着在选择一个与其相邻的节点3,当一条路遍历完后再选择最近一个遍历过的、且相邻节点未遍历过的节点,重复上述操作,直至将图的点遍历完。适合用进行执行

广度搜索的基本方式是由图的一个节点出发,然后遍历所有与其相邻的节点,接着再遍历与相邻节点相邻的节点,重复上述步骤,直至将图上的节点遍历完

遍历的关键是如何判断节点是否已经遍历过,可以定义一个辅助结构体进行判断,结构体里储存的是节点和与之相关的系数flag,未遍历时flag为1,遍历flag后置为0。

这里我分别用邻接矩阵实现DFS,用邻接表实现BFS

二,代码部分

必要头文件及必要设置

#include <iostream>
#define MVNum 100       //最大顶点数 
#define MaxInt 32767   //极大值,即无限 
#include<stack>        //栈的头文件
#define PrintLine printf("\n") //换行
using namespace std;

辅助结构体的定义 

//定义辅助结构体类型
typedef struct Vexs{
	char vex;
	int flag;
}Vex[MVNum];

初始化方式是将图的节点依次存入,flag全部置为1

邻接矩阵储存的图的初始化

	for(int i=0;i<G.vexnum;i++)//初始化辅助结构体 
	{
		V[i].vex=G.vexs[i];
		V[i].flag=1;//将每个节点的flag置为1
	}

邻接表储存的图的初始化

for(int i=0;i<G.vexnum;i++)//初始化辅助结构体 
		{
			V[i].vex=G.vertices[i].data;
			V[i].flag=1;//将每个节点的flag置为0 
		}

判断是否完全遍历完成

//判断是否遍历完
int IsAllPrint(Vex V,int n)
{
	int flag = 1;
	for(int i = 0;i<n;i++)
	{
		if(V[i].flag==1) return 0;
	}
	return 1;
} 

邻接矩阵储存图的基本操作

// 邻接矩阵储存图
typedef struct{
	char vexs[MVNum];    //顶点表 
	int arcs[MVNum][MVNum];  //邻接矩阵 
	int vexnum,arcnum; //图的当前点数和边数 
}AMGraph;

//返回顶点v在图中顶点表的位置 (邻接矩阵)
int LocateVex1(AMGraph &G,char v)
{
	for(int i=0;i<G.vexnum;++i)
		if(G.vexs[i]==v)
			return i;
	 
}

//创建邻接矩阵 
void CreateUDM(AMGraph &G)  
{
	char v1,v2;
	int w,i,j,k;
	cout<<"请输入总定点数与总边数:"<<endl;
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;++i)
	{
		cout<<"请输入第"<<i+1<<"个点"<<endl; 
		cin>>G.vexs[i];
	}
	
	for(i=0;i<G.vexnum;++i)//初始化矩阵,使权值全为最大值 
		for(int j=0;j<G.vexnum;++j)
			G.arcs[i][j]=MaxInt;
			
	for(k=0;k<G.arcnum;++k)
	{
		cout<<"请输入两个顶点以及它们连成边的权值:"<<endl;
		cin>>v1>>v2>>w;
		i = LocateVex1(G,v1);j=LocateVex1(G,v2); //返回顶点的位置 
		G.arcs[i][j]=w;    //赋予权值 
		G.arcs[j][i]=G.arcs[i][j];  //将其对称点赋予相同的权值 
	}
}
//输出矩阵 
void PrintUDM(AMGraph &G)
{
	for(int i=0;i<G.vexnum;i++)
		{
			for(int j=0;j<G.vexnum;j++)
			{
				if(G.arcs[i][j]==MaxInt)
				printf("  ∞");
				else
				printf("%3d ",G.arcs[i][j]);
			}
			cout<<endl;
		}
}
//遍历图(邻接矩阵)
void DFS(AMGraph &G)
{
	Vex V;
	stack<struct Vexs> S;
	int i,j;
	for(int i=0;i<G.vexnum;i++)//初始化辅助结构体 
	{
		V[i].vex=G.vexs[i];
		V[i].flag=1;//将每个节点的flag置为1
	}
	S.push(V[0]);
	cout<<V[0].vex<<" ";
	V[0].flag=0;
	for(i=0;i<G.vexnum;i++)
	{
		int tag = 1;
		for(j=0;j<G.vexnum;j++)
		{
			if(G.arcs[i][j]!=MaxInt&&V[j].flag==1)
			{
				cout<<V[j].vex<<" ";
				S.push(V[j]);
				V[j].flag = 0;
				i = j - 1;
				tag = 0;
				break;
			}
		}
		if(tag==1) 
		{
			i = LocateVex1(G,S.top().vex)-1;
			S.pop();
		}
		if(IsAllPrint(V,G.vexnum)) break;
	}
} 

邻接表储存图的基本操作

//邻接表储存图
typedef struct Arcnode{ //边结点 
	int adjvex;   //该边所指顶点位置 
	struct Arcnode *nextarc;  //指向下一条边的指针 
	int longth; //边的权值 
}ArcNode;

typedef struct Vnode{  //顶点信息 
	char data;         //顶点 
	ArcNode *firstarc;   //指向第一条依附该顶点的边的指针 
}VNode,AdjList[MVNum]; //AdjList表示邻接表类型

typedef struct{
	AdjList vertices;//定义邻接表 
	int vexnum,arcnum; //图的顶点数与边数 
}ALGraph; 
//返回顶点v在图的顶点表的位置 
int LocateVex2(ALGraph &G,char v)
{
	for(int i =0;i<G.vexnum;++i)
		if(G.vertices[i].data==v)
			return i;
} 
//创建邻接表
void CreateUDG(ALGraph &G)
{
	int i,j,k,w;
	char v1,v2;
	ArcNode *p1,*p2;
	cout<<"请输入顶点数与边数:"<<endl;
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;++i)
	{
		cout<<"请输入第"<<i+1<<"个顶点"<<endl;
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc=NULL;  //初始化表头结点的指针域 
	 } 
	 for(k=0;k<G.arcnum;++k)
	 {
	 	cout<<"请输入两个顶点与所连成边的权值"<<endl;
		cin>>v1>>v2>>w; 
		i=LocateVex2(G,v1);j=LocateVex2(G,v2);
		
		p1 = new ArcNode;
		p1->adjvex=j;
		p1->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=p1;
		G.vertices[i].firstarc->longth=w;
		
		//进行对称处理 
		p2 = new ArcNode;
		p2->adjvex=i;
		p2->nextarc=G.vertices[j].firstarc;
		G.vertices[j].firstarc=p2;
		G.vertices[j].firstarc->longth=w;
	} 
 }
//输出邻接表 
void PrintUDG(ALGraph &G)
{
	ArcNode *p;
	VNode *q;
	for(int i=0;i<G.vexnum;i++)
	{
		printf("%2c",G.vertices[i].data);
		p = G.vertices[i].firstarc;
		while(p!=NULL)
		{
			printf("%2c",G.vertices[p->adjvex].data);
			p=p->nextarc;
		}
		printf("\n");	
	}
}
//邻接表遍历
void BFS(ALGraph &G,Vex V,int i)//i为节点位置 
{
	if(IsAllPrint(V,G.vexnum))return; 
	ArcNode *p=G.vertices[i].firstarc;
	if(V[i].flag==1)
	{
		cout<<G.vertices[i].data<<" ";
		V[i].flag=0;
	}
	while(p!=NULL)
	{
		if(V[p->adjvex].flag==1)
		{
			cout<<G.vertices[p->adjvex].data<<" ";
			V[p->adjvex].flag=0;
			BFS(G,V,p->adjvex);
		}
		p=p->nextarc;
		if(IsAllPrint(V,G.vexnum)) return;
		
	}
} 

 三,完整代码

#include <iostream>
#define MVNum 100       //最大顶点数 
#define MaxInt 32767   //极大值,即无限 
#include<stack> //栈的头文件
#define PrintLine printf("\n")//换行 
using namespace std;
//定义辅助结构体类型
typedef struct Vexs{
	char vex;
	int flag;
}Vex[MVNum];

//判断是否遍历完
int IsAllPrint(Vex V,int n)
{
	int flag = 1;
	for(int i = 0;i<n;i++)
	{
		if(V[i].flag==1) return 0;
	}
	return 1;
} 
// 邻接矩阵储存图
typedef struct{
	char vexs[MVNum];    //顶点表 
	int arcs[MVNum][MVNum];  //邻接矩阵 
	int vexnum,arcnum; //图的当前点数和边数 
}AMGraph;

//返回顶点v在图中顶点表的位置 (邻接矩阵)
int LocateVex1(AMGraph &G,char v)
{
	for(int i=0;i<G.vexnum;++i)
		if(G.vexs[i]==v)
			return i;
	 
}

//创建邻接矩阵 
void CreateUDM(AMGraph &G)  
{
	char v1,v2;
	int w,i,j,k;
	cout<<"请输入总定点数与总边数:"<<endl;
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;++i)
	{
		cout<<"请输入第"<<i+1<<"个点"<<endl; 
		cin>>G.vexs[i];
	}
	
	for(i=0;i<G.vexnum;++i)//初始化矩阵,使权值全为最大值 
		for(int j=0;j<G.vexnum;++j)
			G.arcs[i][j]=MaxInt;
			
	for(k=0;k<G.arcnum;++k)
	{
		cout<<"请输入两个顶点以及它们连成边的权值:"<<endl;
		cin>>v1>>v2>>w;
		i = LocateVex1(G,v1);j=LocateVex1(G,v2); //返回顶点的位置 
		G.arcs[i][j]=w;    //赋予权值 
		G.arcs[j][i]=G.arcs[i][j];  //将其对称点赋予相同的权值 
	}
}
//输出矩阵 
void PrintUDM(AMGraph &G)
{
	for(int i=0;i<G.vexnum;i++)
		{
			for(int j=0;j<G.vexnum;j++)
			{
				if(G.arcs[i][j]==MaxInt)
				printf("  ∞");
				else
				printf("%3d ",G.arcs[i][j]);
			}
			cout<<endl;
		}
}
//遍历图(邻接矩阵)
void DFS(AMGraph &G)
{
	Vex V;
	stack<struct Vexs> S;
	int i,j;
	for(int i=0;i<G.vexnum;i++)//初始化辅助结构体 
	{
		V[i].vex=G.vexs[i];
		V[i].flag=1;//将每个节点的flag置为1
	}
	S.push(V[0]);
	cout<<V[0].vex<<" ";
	V[0].flag=0;
	for(i=0;i<G.vexnum;i++)
	{
		int tag = 1;
		for(j=0;j<G.vexnum;j++)
		{
			if(G.arcs[i][j]!=MaxInt&&V[j].flag==1)
			{
				cout<<V[j].vex<<" ";
				S.push(V[j]);
				V[j].flag = 0;
				i = j - 1;
				tag = 0;
				break;
			}
		}
		if(tag==1) 
		{
			i = LocateVex1(G,S.top().vex)-1;
			S.pop();
		}
		if(IsAllPrint(V,G.vexnum)) break;
	}
} 

//邻接表储存图
typedef struct Arcnode{ //边结点 
	int adjvex;   //该边所指顶点位置 
	struct Arcnode *nextarc;  //指向下一条边的指针 
	int longth; //边的权值 
}ArcNode;

typedef struct Vnode{  //顶点信息 
	char data;         //顶点 
	ArcNode *firstarc;   //指向第一条依附该顶点的边的指针 
}VNode,AdjList[MVNum]; //AdjList表示邻接表类型

typedef struct{
	AdjList vertices;//定义邻接表 
	int vexnum,arcnum; //图的顶点数与边数 
}ALGraph; 
//返回顶点v在图的顶点表的位置 
int LocateVex2(ALGraph &G,char v)
{
	for(int i =0;i<G.vexnum;++i)
		if(G.vertices[i].data==v)
			return i;
} 
//创建邻接表
void CreateUDG(ALGraph &G)
{
	int i,j,k,w;
	char v1,v2;
	ArcNode *p1,*p2;
	cout<<"请输入顶点数与边数:"<<endl;
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;++i)
	{
		cout<<"请输入第"<<i+1<<"个顶点"<<endl;
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc=NULL;  //初始化表头结点的指针域 
	 } 
	 for(k=0;k<G.arcnum;++k)
	 {
	 	cout<<"请输入两个顶点与所连成边的权值"<<endl;
		cin>>v1>>v2>>w; 
		i=LocateVex2(G,v1);j=LocateVex2(G,v2);
		
		p1 = new ArcNode;
		p1->adjvex=j;
		p1->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=p1;
		G.vertices[i].firstarc->longth=w;
		
		//进行对称处理 
		p2 = new ArcNode;
		p2->adjvex=i;
		p2->nextarc=G.vertices[j].firstarc;
		G.vertices[j].firstarc=p2;
		G.vertices[j].firstarc->longth=w;
	} 
 }
//输出邻接表 
void PrintUDG(ALGraph &G)
{
	ArcNode *p;
	VNode *q;
	for(int i=0;i<G.vexnum;i++)
	{
		printf("%2c",G.vertices[i].data);
		p = G.vertices[i].firstarc;
		while(p!=NULL)
		{
			printf("%2c",G.vertices[p->adjvex].data);
			p=p->nextarc;
		}
		printf("\n");	
	}
}
//邻接表遍历
void BFS(ALGraph &G,Vex V,int i)//i为节点位置 
{
	if(IsAllPrint(V,G.vexnum))return; 
	ArcNode *p=G.vertices[i].firstarc;
	if(V[i].flag==1)
	{
		cout<<G.vertices[i].data<<" ";
		V[i].flag=0;
	}
	while(p!=NULL)
	{
		if(V[p->adjvex].flag==1)
		{
			cout<<G.vertices[p->adjvex].data<<" ";
			V[p->adjvex].flag=0;
			BFS(G,V,p->adjvex);
		}
		p=p->nextarc;
		if(IsAllPrint(V,G.vexnum)) return;
		
	}
} 
void Menu()
{
	int choice;
	cout<<"================================"<<endl;
	cout<<"1.邻接矩阵创建图\n"<<"2.邻接表创建图\n";
	cout<<"================================"<<endl;
	cout<<"请输入你要进行的操作:" <<endl;
	cin>>choice;
	if(choice==1)
	{
		AMGraph G;
		CreateUDM(G);
		PrintLine;
		PrintUDM(G);
		PrintLine;
		DFS(G);
		
	}
	else if(choice==2)
	{
		ALGraph G;
		CreateUDG(G);
		PrintLine;
		PrintUDG(G);
		PrintLine;
		Vex V;
		for(int i=0;i<G.vexnum;i++)//初始化辅助结构体 
		{
			V[i].vex=G.vertices[i].data;
			V[i].flag=1;//将每个节点的flag置为0 
		}
			BFS(G,V,0);
		}
	else
	cout<<"输入错误!";
	 
}

int main()
{
 	Menu();
 	return 1;
	
}

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

无向图的遍历-BFS与DFS 的相关文章

  • 算法设计与实现--贪心篇

    贪心算法 贪心算法是一种在每一步选择中都采取当前状态下最优决策的算法 以期望能够通过一系列局部最优的选择达到全局最优 贪心算法的关键是定义好局部最优的选择 并且不回退 即一旦做出了选择 就不能撤销 一般来说 贪心算法适用于满足以下两个条件的
  • 算法设计与实现--动态规划篇

    什么是动态规划算法 动态规划算法是一种求解复杂问题的方法 通过将原问题分解为相对简单的子问题来求解 其基本思想是将待求解的问题分解为若干个子问题 阶段 按顺序求解子阶段 前一子问题的解 为后一子问题的求解提供了有用的信息 在求解任一子问题时
  • 【数据结构/C++】树和二叉树_二叉链表

    include
  • E (1052) : DS树--带权路径和

    文章目录 一 题目描述 二 输入与输出 1 输入 2 输出 三 参考代码 一 题目描述 计算一棵二叉树的带权路径总和 即求赫夫曼树的带权路径和 已知一棵二叉树的叶子权值 该二叉树的带权路径和APL等于叶子权值乘以根节点到叶子的分支数 然后求
  • 【数据结构】双链表的定义和操作

    目录 1 双链表的定义 2 双链表的创建和初始化 3 双链表的插入节点操作 4 双链表的删除节点操作 5 双链表的查找节点操作 6 双链表的更新节点操作 7 完整代码 嗨 我是 Filotimo 很高兴与大家相识 希望我的博客能对你有所帮助
  • DS八大排序之冒泡排序和快速排序

    前言 前两期我们已经对 插入排序 直接插入排序和希尔排序 和 选择排序 直接选择排序和堆排序 进行了详细的介绍 这一期我们再来详细介绍一组排序 交换排序 即耳熟能详的冒泡排序和赫赫有名的快速排序 本期内容介绍 冒泡排序 快速排序 Hoare
  • 剑指 Offer(第2版)面试题 35:复杂链表的复制

    剑指 Offer 第2版 面试题 35 复杂链表的复制 剑指 Offer 第2版 面试题 35 复杂链表的复制 解法1 模拟 剑指 Offer 第2版 面试题 35 复杂链表的复制 题目来源 48 复杂链表的复刻 解法1 模拟 算法 复制原
  • 数据结构 数组与字符串

    介绍 数组的基础 定义和声明 基本定义 在C语言中 数组可以被定义为一系列相同类型的元素的集合 每个元素在内存中连续排列 可以通过索引 通常是从0开始的整数 来访问 数组的声明 数组在C语言中的声明包括元素类型 数组名和大小 例如 声明一个
  • 深度学习目标检测全连接层什么意思

    在深度学习目标检测中 通常我们使用卷积神经网络 Convolutional Neural Network CNN 进行特征提取 CNN 的主要结构包括卷积层和池化层 用于从输入图像中提取特征 然而 为了最终输出目标的类别和位置信息 通常在网
  • 力扣每日一题:162. 寻找峰值(2023-12-18)

    力扣每日一题 题目 162 寻找峰值 日期 2023 12 18 用时 10 m 9 s 时间 0 ms 内存 40 54 MB 代码 class Solution public int findPeakElement int nums i
  • 【华为OD】给定一个整数数组nums,请你在该数组中找出两个数,使得这两个数 的和的绝对值abs(nums[x] + nums[y])为最小值并按从小到大返回这 两个数以及它们和的绝对值

    题目描述 给定一个整数数组nums 请你在该数组中找出两个数 使得这两个数 的和的绝对值abs nums x nums y 为最小值并按从小到大返回这 两个数以及它们和的绝对值 每种输入只会对应一个答案 数组中同一 个元素不能使用两遍 输入
  • 面试150-13(Leetcode238除自身以外数组的乘积)

    代码 class Solution public int productExceptSelf int nums int n nums length int res new int n int product 1 int zerocnt 0
  • 数组对象排序 (arr.sort())

    前端面试题库 面试必备 推荐 地址 前端面试题库 对象排序 arr sort 描述 方法sort 将在原数组上对 数组元素 进行排序 即排序时不创建新的数组副本 如果想按照别的顺序进行排序 就必须提供比较函数 该函数要比较两个值 然后返回一
  • 代码随想录算法训练营第42天| ● 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集

    416 分割等和子集 已解答 中等 相关标签 相关企业 给你一个 只包含正整数 的 非空 数组 nums 请你判断是否可以将这个数组分割成两个子集 使得两个子集的元素和相等 示例 1 输入 nums 1 5 11 5 输出 true 解释
  • 860.染色法判定二分图

    二分图是指一个图中的所有顶点可以分为两部分 并且每条边连接的是属于不同部分的两个顶点 include
  • 浅谈归并排序:合并 K 个升序链表的归并解法

    在面试中遇到了这道题 如何实现多个升序链表的合并 这是 LeetCode 上的一道原题 题目具体如下 用归并实现合并 K 个升序链表 LeetCode 23 合并K个升序链表 给你一个链表数组 每个链表都已经按升序排列 请你将所有链表合并到
  • 矩阵基本操作3

    题目描述 问题描述 定义一个N M N M lt 100 的矩阵 将一个该矩阵的行和列的元素互换 存到另一个二维数组中 输入格式 一行两个整数 N M 中间用空格隔开 表示矩阵有N行 M列 接下来共N行M列表示矩阵 输出格式 输出转置以后的
  • 单向不带头链表的使用

    单向不带头链表的使用 链表的创建 typedef struct LNode SLDataType data struct LNode next LNode LinkList 按位查找 LNode GetElem LinkList L int
  • 「优选算法刷题」:移动零

    嗨 这个假期罗根开始接触了算法 在为今年的蓝桥杯做准备 所以 开个新专栏 记录记录自己做算法题时的心得 一 题目 给定一个数组 nums 编写一个函数将所有 0 移动到数组的末尾 同时保持非零元素的相对顺序 请注意 必须在不复制数组的情况下
  • 高精度运算合集,加减乘除,快速幂,详细代码,OJ链接

    文章目录 零 前言 一 加法 高精度加法步骤 P1601 A B 二 减法 高精度减法步骤

随机推荐

  • 解决 in ./node_modules/cesium/Source/ThirdParty/zip.js报错

    由于在 node modules cesium Source ThirdParty zip js 文件中使用了 import meta 语法 webpack 默认不支持 在进行项目构建时 会报如下错误 提示信息需要添加 loader 接下来
  • 谷歌浏览器配置微信浏览器_使用Chrome修改user agent模拟微信内置浏览器

    很多时候 我们需要模拟微信内置浏览器 今天教大家用chrome简单模拟 如图设置 F12或者右键审查元素进入开发者模式 点击Emulation 然后点击Network 把Spoof user agent改成Other 并把下面的带复制进去
  • PaddleSpeech调研、安装、使用

    PaddleSpeech概述 PaddleSpeech asr 模块目前只支持中英文的语音自动识别 建议在Linux环境下安装和使用 配置环境要求 gcc gt 4 8 5 paddlepaddle gt 2 4 1 python gt 3
  • 概率论与数理统计

    目录 一 概率论的基本概念 1 1 概率论的直观解释和数学定义 1 2 条件概率与乘法公式 1 3 全概率公式与贝叶斯公式 1 4 事件的独立性 二 随机变量与分布函数 2 1 随机变量与分布函数 2 2 离散型随机变量和常用分布 2 3
  • 定时任务——Cron表达式详解

    Cron表达式是一个字符串 字符串以5或6个空格隔开 分为6或7个域 每一个域代表一个含义 Cron有如下两种语法格式 Seconds Minutes Hours DayofMonth Month DayofWeek Year或 Secon
  • C++ : 在一个string字符串中查找给定的字符串并提取

    C 在一个string字符串中查找给定的字符串并提取 1 string find last of 返回类型 size t 2 string find first of 返回类型 size t 3 string substr size t a
  • 力扣刷题-面试题 17.13. 恢复空格、字典树、前缀树的应用

    基本概念 Trie 树 又称单词查找树 前缀树 是一种树形结构 典型应用是用于统计 排序和保存大量的字符串 但不仅限于字符串 它的优点是 利用字符串的公共前缀来减少查询时间 最大限度地减少无谓的字符串比较 比哈希表更快 基本性质 根节点不包
  • 正负样本分配策略(OTA, SimOTA,TAS)

    文章目录 OTA SimOTA TAL ATSS OTA 论文 OTA Optimal Transport Assignment for Object Detection 代码 Megvii BaseDetection OTA 标签分配算法
  • c++静态代码扫描工具clang-tidy详细介绍

    clang tidy 文章目录 clang tidy 1 什么是clang tidy 2 clang tidy可以解决什么问题 3 工作原理 4 如何使用clang tidy 4 总结 5 举例说明 1 什么是clang tidy Clan
  • 十五年学不会英语的原因

    学习前预热 轻松学英语第一步 建立英语思维 为什么大家学英语学得这么累 最后依然对英语糊糊涂涂 原因只有一个 就是我们的学习能力太差了 我们的老师太笨了 这篇文章主要是给大家讲英语的基本结构 看了这篇文章 你们会突然就明白 英语怎么会如此简
  • 第19章:python自动化——ChromeOptions与WebUI实操

    目录 一 ChromeOptions设置项 二 WebUI实操 一 ChromeOptions设置项 浏览器在启动之初 如果需要对浏览器进行一些特定内容的定义 可以直接通过浏览器的options类来实现相对应的配置内容 不同的浏览器有不同的
  • Vue中如何配置自定义路径别名

    Vue中如何配置自定义路径别名 在我们日常开发中 常常会导入一些模块或者组件 如果采用相对路径的方式 import uEditor from components tools 会显得臃肿 多余 如果引用稍有差错就会出现 404的报错 不优雅
  • A Survey on Large Language Model based Autonomous Agents

    本文是LLM系列的文章 针对 A Survey on Large Language Model based Autonomous Agents 的翻译 基于大模型的自动agents综述 摘要 1 引言 2 基于LLM的自动代理构建 3 基于
  • 学网络安全都是一群什么人?

    大家好呀 我是知了姐 又是一期学员故事栏目 3月下旬知了堂信安方向开新班 知了姐跟着去采访 了解到新学员们的求学故事 嘿你别说 虽然大家出身专业不同 经历背景不同 如今却在同一个地点相遇 加入到知了堂这个大家庭 不同专业 年龄的他们 为什么
  • 格式工厂5.10.0版本安装

    目前格式工厂有很多 大多都可以进行视频转换 之前遇到一个用ffmpeg拉流保存的MP4在vlc和迅雷都无法正常播放的问题 发现视频长度不对 声音也不对 最后换到了格式工厂的格式播放器是可以正常播放的 格式工厂下载之家的地址 https ww
  • OSG for Android新手教程系列(二)——项目配置

    在上一篇教程中 主要介绍了如何把OSG源代码编译成为能够在Android项目下使用的函数库 在这一篇教程中 我将针对如何在自己的Android项目中配置OSG函数库进行详细讲解 现阶段网上关于OSGfor Android的配置方式教程有很多
  • 用户登录的详细流程(二)JWT生成token登录

    JWT生成token登录 1 jwt的构成 1 header 2 payload 3 signature 2 token的登陆原理 3 在实际中如何应用token 1 设置token的生成代码 2 如何从token中获取有用的信息 3 验证
  • 汇编程序设计与计算机体系结构软件工程师教程笔记:总结

    汇编程序设计与计算机体系结构 软件工程师教程 这本书是由Brain R Hall和Kevin J Slonka著 由爱飞翔译 中文版是2019年出版的 个人感觉这本书真不错 书中介绍了三种汇编器GAS NASM MASM异同 全部示例代码都
  • EC11旋转编码器、stm32f103驱动程序

    1 EC11手册的要点 注意 旋转的速度 RC滤波 手册中推荐的电路 已含有RC滤波 输出波形特点 2 硬件电路 加上RC滤波电路 做法是两个端点都采用10pF电容接地 10K 电阻接VCC 实测100pF电容也行 用示波器看看波形有无噪声
  • 无向图的遍历-BFS与DFS

    一 理论部分 无向图的遍历可用深度搜索 DFS 与广度搜索 BFS 深度搜索的基本方式是由图的一个节点1出发然后随机选一个与其相邻的节点2 接着在选择一个与其相邻的节点3 当一条路遍历完后再选择最近一个遍历过的 且相邻节点有未遍历过的节点