【数据结构】时间、空间复杂度实例分析

news2024/9/17 8:25:10

跌倒了,就重新站起来,继续向前走;傻坐在地上是没用的。💓💓💓

目录

•✨说在前面

🍋知识点一:算法的效率

  • 🌰1.斐波那契数列的第n项

 • 🌰2.算法的复杂度

🍋知识点二:时间复杂度

  • 🌰1.时间复杂度的概念

 • 🌰2.大O的渐进表示法

🔥复杂度的一般分析法则

🔥总结求解复杂度的方法

 • 🌰3.时间复杂度的量级

 • 🌰4.时间复杂度增长趋势​​​​​​​

  • 🌰5.时间复杂度计算案例

🔥案例1:单个同量级for循环

🔥案例2:多个同量级for循环

🔥案例3:常数控制的for循环

🔥案例4:strchr函数的时间复杂度

🔥案例5:冒泡排序的时间复杂度

🔥案例6:调整语句为i=i*2的for循环

🔥案例7:二分查找的时间复杂度

🔥案例8:递归求阶乘

🔥案例9:递归求斐波那契数列的第n项

🍋知识点三:空间复杂度

   • 🌰1.空间复杂度的概念

  • 🌰2.空间复杂度计算案例

🔥案例1:冒泡排序的空间复杂度

🔥案例2:递归求阶乘

• ✨SumUp结语


•✨说在前面

亲爱的读者们大家好!💖💖💖,我们又见面了,在之前的阶段我们学习了顺序表、链表,包括单链表和双向链表,还刷了一些算法OJ练习。这些练习,我们有时可以有多种思路和方法解决,那我们如何对这些方法进行取舍呢?哪些方法是最优的呢?为此,我们必须进入学习时间复杂度和空间复杂度的相关知识,相信你学习完后就可以回答这个问题了。

   

 👇👇👇
💘💘💘知识连线时刻(直接点击即可)

  🎉🎉🎉复习回顾🎉🎉🎉

【数据结构】顺序表专题详解(带图解析)

【数据结构】单链表专题详细分析

【数据结构】双向循环链表专题解析

    

  博主主页传送门:愿天垂怜的博客

🍋知识点一:算法的效率

  • 🌰1.斐波那契数列的第n项

在讲解时间复杂度与空间复杂度之前,我们先看一个简单的例子:

练习:写一个程序,求出斐波那契数列的第n项的值。

方法1:迭代法

long long Fibonacci(int n)
{
	int x1 = 1;
	int x2 = 1;
	int x3 = 1;
	while (n >= 3)
	{
		x3 = x1 + x2;
		x1 = x2;
		x2 = x3;
		n--;
	}
	return x3;
}

方法2:递归法

long long Fibonacci(int n)
{
	if (n == 1 || n == 2)
		return 1;
	return Fibonacci(n - 1) + Fibonacci(n - 2);
}

由观察不难发现,递归的写法明显要比迭代的写法要短的多,那是不是就说明递归的写法就比迭代的写法更好呢?其实不然,实际上用递归来写的话它的运行效率将会大大降低。

比如求第50项,就要先得到49项和48项,要得到第49项,就要得到48项和47项……它会执行很多很多次,这是它效率不高的原因。

所以,项数较大时,我们还是用循环(迭代)的方式来实现。

所以说,我们不能只根据程序的长短就果断地判断程序的好坏。

 • 🌰2.算法的复杂度

那究竟如何衡量算法的好坏呢?就是要看程序的时间复杂度空间复杂度。

算法在编写成可执行的程序后,运行时需要耗费时间资源和空间(内存)资源,因此衡量一个算法好坏,一般从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。

时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。在计算机发展的早期,计算机的存储容量很小,所以对于空间复杂度很是在乎,但结果计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度,所以我们如今已经不需要再特别关注一个算法的空间复杂度,转而更加关注他的时间复杂度。

🍋知识点二:时间复杂度

  • 🌰1.时间复杂度的概念

定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。

一个算法执行所消耗的时间,从理论上来说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?这显然非常麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比,算法中的基本操作的执行次数,为算法的时间复杂度。

即:找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度。

 • 🌰2.大O的渐进表示法

实际问题中我们不需要精确的计算执行次数,而只需要大概的执行次数,即使用大O的渐进表示法。

公式如下:

🎉参数:

• T(n):代码执行所需要的时间,它是n的函数,T(n)代表了算法的时间复杂度。

• n:数据规模的大小,但有可能不止一个,如两个for循环分别循环m、n次,则该参数为m、n。

• f(n):每行代码执行的次数总和,它是n的函数,但我们只关注最大量级的那一项。

• O:表示T(n)与f(n)之间的关系为正比例,即一个算法所花费的时间与其中语句的执行次数成正比。

🔥复杂度的一般分析法则

1)单端代码看高频:比如for、while循环。

2)多段代码取最大:比如一段代码中有单循环和多重循环,那么取多重循环的复杂度。

3)嵌套代码求乘积:例如递归、多重循环的结构。

4)多个规模求加法:比如算法中有两个参数控制了两个for循环,那么此时复杂度取二者复杂度之和。

🎉举例:

//请计算一下Func1中++count语句总共执行了多少次?
void Func(int n)
{
	int count = 0;
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			++count;
		}
	}

	for (int k = 0; k < 2 * n; ++k)
	{
		++count;
	}
	int M = 10;
	while (M--)
	{
		++count;
	}
	printf("%d\n", count);
}

根据复杂度的分析原则,在上面的这个函数Func1中,第一个循环是嵌套结构,for循环嵌套结构执行了n^2次,第二个for循环执行了2n次,最后一个while循环执行了10次。

由此,这个函数中基本语句的执行次数f(n)的表达式为:f(n)=n^2+2n+10,所以T(n)=O(n^2+2n+10)。但是,大O的渐进表示法并不具体代表代码真正的执行时间,而是代表代码执行时间随数据规模n增长的变化趋势。

当n很大时,比如1000、100000,此时公式中的低阶、常量、系数三部分不左右增长趋势,所以都可以忽略,只关注最高阶的那一项就可以了。

所以最终,Func的时间复杂度表示为:T(n)=O(n^2)。

🔥总结求解复杂度的方法

1)只关注循环执行次数最多的一段代码,总复杂度等于量级最大的那段代码的复杂度

2)加法法则:若控制两个for循环的数量级相同,则总复杂度取二者复杂度之和。

3)乘法法则:嵌套循环的复杂度等于嵌套内外代码复杂度的乘积。

 • 🌰3.时间复杂度的量级

多项式阶:随着数据规模的增长,算法的执行时间和空间占用,按照多项式的比例增长,包括:O(1)(常数阶)、O(logn)(对数阶)、O(n)(线性阶)、O(nlogn)(线性对数阶)、O(n^2)(平方阶)、O(n^3)(立方阶)。

非多项式阶:随着数据规模的增长,算法的执行时间和空间占用暴增,这类算法性能极差。包括,
O(2^n)(指数阶)、O(n!)(阶乘阶)。

 

 • 🌰4.时间复杂度增长趋势

常见不同数量级的复杂度增长趋势图如下:

 另外有些算法的时间复杂度存在最好、平均和最快的情况:

🎉最坏情况:代码在最坏情况下执行的时间复杂度,即任意输入规模的最大运行次数(上界)。

🎉平均情况:代码在所有情况下执行的次数的加权平均值,即任意输入规模的期望运行次数。

🎉最好情况:代码在最理想情况下执行的时间复杂度,任意输入规模的最小运行次数(下界)。

比如:在一个长度为N的数组中搜索数据x

最坏情况:N次找到

平均情况:N/2次找到

最好情况:1次找到

在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据的时间复杂度为O(N)。

  • 🌰5.时间复杂度计算案例

🔥案例1:单个同量级for循环

计算Func2的时间复杂度。

void Func2(int N)
{
	int count = 0;
	for (int k = 0; k < 2 * N; ++k)
	{
		++count;
	}
	int M = 10;
	while (M--)
	{
		++count;
	}
	printf("%d\n", count);
}

函数Func2中,第一个for循环执行了2N次,第二个while循环的执行次数是M,但是M为已知量10,量级最大的为2N,所以Func2的时间复杂度为O(N)

🔥案例2:多个同量级for循环

计算Func3的时间复杂度。

void Func3(int N, int M)
{
	int count = 0;
	for (int k = 0; k < M; ++k)
	{
		++count;
	}
	for (int k = 0; k < N; ++k)
	{
		++count;
	}
	printf("%d\n", count);
}

函数Func3中,第一个for循环执行了M次,第二个for循环执行了N次,且M、N量级相同,所以Func3的时间复杂度为O(M+N),或O(max(M,N))

注意:若M>>N,则时间复杂度为O(M),若M<<N,则时间复杂度为O(N)。

🔥案例3:常数控制的for循环

计算Func4的时间复杂度。

void Func4(int N)
{
	int count = 0;
	for (int k = 0; k < 100; ++k)
	{
		++count;
	}
	printf("%d\n", count);
}

函数Func4中,控制for循环的次数为常数,代码不随n的增长而增长,常数阶的时间复杂度为O(1),即Func4的时间复杂度为O(1)

🔥案例4:strchr函数的时间复杂度

strchr:strchr() 用于查找字符串中的一个字符,并返回该字符在字符串中第一次出现的位置。

strchr函数模拟实现代码如下:

const char* my_strchr(const char* str, int character)
{
	assert(str);
	while (*str)
	{
		if (*str == character)
			return str;
		else
			str++;
	}
}

在strchr查找的过程中,最好的情况是字符character就在下一个字符,一次就可以找到,也就是常数阶,此时时间复杂度为O(1);最坏的情况是字符character在离位置的无穷远处,也就是线性阶。此时时间复杂度为O(N);取最坏的情况,所以strchr的时间复杂度为O(N)

🔥案例5:冒泡排序的时间复杂度

计算冒泡排序BubSort的时间复杂度。

void bubSort(int arr[], int length)
{
	assert(arr);
	int flag = 1;
	while (flag && length--)
	{
		flag = 0;
		for (int i = 0; i < length; i++)
		{
			if (arr[i] > arr[i + 1])
			{
				int temp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = temp;
				flag = 1;
			}
		}
	}
}

冒泡排序中,由类似案例2的嵌套循环结构,但是像案例2这样的嵌套循环,它的内层for循环的控制参数是不变的,也就是说,内部循环一共执行了M次,每次执行内部循环都需要循环N次,所以总共的执行次数是M*N,这很好理解,但现在冒泡排序的内部循环一共执行了length次,而第一次for循环length次,第二次length-1次,第三次length-2次...,若考虑最坏的情况,最后到1次。这种情况怎么处理呢?

显然内部for循环的循环次数是一个等差数列,其中公差d=2,首项a1=1,尾项an=length(简写为n),项数为length。对于这样一个等差数列,我们可以对其求和,所得到的结果不就是所有的执行次数了吗?

根据高斯求和公式,很容易计算出等差数列的前n项和,即基本操作的执行次数,显然为平方阶,量级为N^2,所以冒泡排序Bubsort的时间复杂度为O(N^2)

其实对于案例2这样每次都是循环固定次数的嵌套,或者说,任意的双层嵌套都可以转化为数列求和的问题,如案例2,显然就是一个公差d=0,首项为N,尾项为N,项数为M的等差数列

 根据高斯求和公式,也能够分析出基本操作的执行次数,即时间复杂度为O(MN)

🔥案例6:调整语句为i=i*2的for循环

计算Func5的时间复杂度。

void Func5(int n)
{
	int x = 0;
	for (int i = 1; i < n; i *= 2)
	{
		x++;
	}
}

函数Func5中,这个for循环的调整语句为i*=2,即i每次都是前一次的两倍。这种循环是有规律的,这个我们后面再说。我们先直接分析这个函数,假设基本语句x++执行了N次,那么有循环语句可得:

所以我们得到,执行次数N为对数阶,所以时间复杂度为O(logN)这里需要注意,为了方便起见,当底数为2时,我们直接将底数2省略不写, 

🔥案例7:二分查找的时间复杂度

计算二分查找BinarySearch的时间复杂度。

int BinarySearch(int arr[], int length, int x)
{
	assert(arr);
	int left = 0;
	int right = length - 1;
	while (left <= right)
	{
		int mid = left + right - ((left - right) >> 1);
		if (arr[mid] < x)
			left = mid + 1;
		else if (arr[mid] > x)
			right = mid - 1;
		else if (mid == x)
			return x;
	}
	return -1;
}

在二分查找函数BinarySearch中,如果我们直接观察while循环的话,其实是不太好看出来的,因为left和right时不时都在改变,此时我们不要死盯代码,一定要理解它的实际意义,也可以看图进行观察

 最好的情况我们很容易想到,就是要查找的x就在中间,我们一下就找到了,此时是时间复杂度为O(1)。那最坏的情况呢?其实就是当要查找的x在数组的两端的时候,比如x是第一个元素,此时我们设mid到x的距离为n,则mid会以每次靠近一半的速度逼近第一个元素x,也就是每次都除以2,直到这个值等于1,就找到了第一个元素。我们设循环执行了N次,mid第一次的位置为n,则

同样地,如果x是最后一个元素,也是同样的道理。显然为对数阶,所以二分查找BinarySearch的

的时间复杂度为O(logN)

🔥案例8:递归求阶乘

计算Fact的时间复杂度。

long long Fact(size_t N)
{
	if (0 == N)
		return 1;

	return Fac(N - 1) * N;
}

这是一个递归求阶乘的函数。在函数Fact中,我们假设N=5的情况如下:

可以发现,每次递归的单个函数都是常数阶,即O(1),而递归总共调用了5+1=6次(Fact(5)、Fact(4)、Fact(3)、Fact(2)、Fact(1)、Fact(0))。

以递归的函数我们先看单个函数内部的阶,再看递归了多少次。如果是N,那么每个函数为O(1),递归了N+1次,那么总共为(N+1)O(1),所以递归求阶乘函数的时间复杂度为O(N)

🔥案例9:递归求斐波那契数列的第n项

计算Fibonacci函数的时间复杂度。

long long Fibonacci(int n)
{
	if (n == 1 || n == 2)
		return 1;
	return Fibonacci(n - 1) + Fibonacci(n - 2);
}

同样的道理,我们看单个函数内部的阶,显然为O(1),那递归了多少次呢?

我们以n=5为例,此时我们能画出面类似于树状图的结构,在数的每个节点都进而伸出两个节点,第一行为个数为1(2^0),第二行个数为2(2^1),第三行个数为4(2^2)...以此类推,第n行的个数为2^n。但其实上大家能看到,这颗树是歪的,它的底部缺失了一块三角形的部分,但是当n很大时,这些缺失的部分相对于整体的个数其实就很少了,由此我们可以将每一行的递归次数看做一项,那整体就可以看做首项a1=1,公比q=2的等比数列,求和得到的即是全体递归的总次数。

虽然真正的递归次数没有这么多,但是它的量级是不会被影响的,依然是指数阶,所以用递归求斐波那契数列的第n项,它的时间复杂度为O(2^N)

稍许有些不严谨,在二叉树的部分我们还会提到。

🍋知识点三:空间复杂度

   • 🌰1.空间复杂度的概念

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的亮度。

空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。

空间复杂度计算规则基本和时间复杂度类似,也是大O渐进表示法。

注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式的额外空间来确定。

  • 🌰2.空间复杂度计算案例

🔥案例1:冒泡排序的空间复杂度

计算冒泡排序BubSort的空间复杂度。

void bubSort(int arr[], int length)
{
	assert(arr);
	int flag = 1;
	while (flag && length--)
	{
		flag = 0;
		for (int i = 0; i < length; i++)
		{
			if (arr[i] > arr[i + 1])
			{
				int temp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = temp;
				flag = 1;
			}
		}
	}
}

在冒泡排序BubSort中,创建了:int flag = 1,int i = 0两个变量,为常数个,所以冒泡排序的空间复杂度为O(1)。 

注意:空间复杂度算的是算法中额外开辟的空间,所以数组arr和长度length并不算在内。

🔥案例2:递归求阶乘

计算Fact函数的空间复杂度。

long long Fact(size_t N)
{
	if (0 == N)
		return 1;

	return Fac(N - 1) * N;
}

对于这样的一个递归函数,每次递归都会在栈上创建栈帧空间(函数栈帧),每个栈帧使用了常数个空间,所以空间复杂度为O(N)

• ✨SumUp结语

数据结构的学习一定要多画图,多理解,多思考,切忌直接抄写代码,就认为自己已经会了,一定到自己动手,才能明白自己哪个地方有问题。

 

如果大家觉得有帮助,麻烦大家点点赞,如果有错误的地方也欢迎大家指出~

 

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

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

相关文章

ChatGPT 4o 使用案例之一

2024年GPT迎来重大更新&#xff0c;OpenAI发布GPT-4o GPT-4o&#xff08;“o”代表“全能”&#xff09; 它可以接受任意组合的文本、音频和图像作为输入&#xff0c;并生成任意组合的文本、音频和图像输出。它可以在 232 毫秒内响应音频输入&#xff0c;平均为 320 毫秒&…

数学建模——建立数学模型(1)

前言 这个也是对《数学模型》&#xff08;姜启源第四版&#xff09;书内容的摘抄 建立数学模型 数学模型这个词汇现在越来越多地出现在现代入的 生产、工作和社会活动中&#xff0e;广大的科学技 术人员和应用数学工作者来说&#xff0c;建立数学模型是沟通摆在面前的实际问…

无人售货奶柜:掘金新零售蓝海,

无人售货奶柜&#xff1a;掘金新零售蓝海&#xff0c; 在日新月异的商业浪潮中&#xff0c;无人奶柜犹如一股清新的创业飓风&#xff0c;正以不可阻挡之势吸引着众多创业者的目光。这股新兴力量以其独到之处和庞大的市场蓝海&#xff0c;预示着一场关于健康、便捷消费方式的深…

荣耀MagicBook X 14 Pro锐龙版 2023 集显(FRI-H76)笔记本电脑原装出厂Windows11系统工厂模式安装包下载,带F10智能还原

恢复开箱状态预装OEM系统&#xff0c;适用型号&#xff1a;HONOR荣耀FRI-H76、FRI-H56 链接&#xff1a;https://pan.baidu.com/s/1Lcg45byotu5kDDSBs3FStA?pwdl30r 提取码&#xff1a;l30r 华为荣耀原装WIN11系统工厂安装包&#xff0c;含F10一键恢复功能、系统自带所有驱…

jvisualvm安装Visual GC插件

给jdk自带的jvisualvm安装Visual GC插件&#xff0c;遇到We’re sorry the java.net site has closed&#xff08;我们很抱歉java.net网站已经关闭&#xff09; 1、找到新的更新地址 visualvm新访问地址&#xff1a;https://visualvm.github.io/index.html 进入“Plugins”&am…

航向数据之海:Spring的JPA与Hibernate秘籍

Hi&#xff0c;俺又来给大家上课啦~ 在数字化的海域中&#xff0c;掌握数据访问与集成的航海术至关重要。本文将带你揭秘Spring框架如何借助JPA与Hibernate这两大法宝&#xff0c;引领开发者在数据库的汪洋中乘风破浪&#xff01; 航向数据之海&#xff1a;Spring的JPA与Hibern…

JavaScript-BOM编程

BOM对象 1 什么是BOM2 window对象的常见属性3 window对象的常见方法4 通过BOM编程控制浏览器行为演示5 通过BOM编程实现会话级和持久级数据存储 1 什么是BOM BOM是Browser Object Model的简写&#xff0c;即浏览器对象模型。 BOM由一系列对象组成&#xff0c;是访问、控制、修…

Vue和Django前后端实现跨域

1.为什么要解决跨域&#xff1a; 前端与后端分处不同的域名&#xff0c;因为客户端访问不同源的服务端时会遭到浏览器的同源策略的拦截&#xff0c;所以我们需要配置CORS&#xff0c;处理的方式有很多&#xff0c;先来说下自己学习到的。 2.前端处理跨域&#xff1a; 前端项目是…

基于HTML5和CSS3搭建一个Web网页(一)

倘若代码中有任何问题或疑问&#xff0c;欢迎留言交流~ 网页描述 创建一个包含导航栏、主内容区域和页脚的响应式网页。 需求: 导航栏: 在页面顶部创建一个导航栏&#xff0c;包含首页、关于我们、服务和联系我们等链接。 设置导航栏样式&#xff0c;包括字体、颜色和背景颜…

Web应用开发中查找慢SQL的方法

每条SQL语句在执行时都需要消耗一定的I/O资源&#xff0c;SQL语句执行的快慢直接决定了硬件资源被占用时长的长短&#xff0c;慢SQL一般指查询很慢的SQL语句。在MySQL数据库中&#xff0c;可以通过慢查询来查看所有执行超时的SQL语句。在默认情况下&#xff0c;一般慢SQL是关闭…

问题-小技巧-Win11-如何把Win11鼠标右键界面变成Win10鼠标右键界面

如果Win10的鼠标右键操作不常用&#xff0c;那就按住shift后再按鼠标右键&#xff0c;就会使用Win10的鼠标右键界面。 如果想彻底改成Win10的操作做界面可以看—— 问题-小技巧-Win11-如何把Win11鼠标右键界面改成Win10鼠标右键界面 这个文章详细的讲解了&#xff0c;如果把…

Vue3:分类管理综合案例实现

综合案例 实现分类管理功能 路由 在main.js中引入router 访问根路径’/后跳转到布局容器 加载布局容器后重定向到’/nav/manage’ 加载我们需要的组件 这样可以在布局容器中切换功能模块时,只对需要修改的组件进行重新加载 const router createRouter({history: create…

深度学习500问——Chapter08:目标检测(9)

文章目录 8.5 目标检测的技巧汇总 8.5.1 Data Augmentation 8.5.2 OHEM 8.5.3 NMS&#xff1a;Soft NMS/ Polygon NMS/ Inclined NMS/ ConvNMS/ Yes-Net NMS/ Softer NMS 8.5.4 Multi Scale Training/Testing 8.5.5 建立小物体与context的关系 8.5.6 参考relation network 8.5.…

Python数据分析——Py基础语法复习(非常详细版)

1.基础数据类型 Number数字、String字符串、List列表、Tuple元组、Set集合、dictionary字典。数字、字符串、元组不可变&#xff0c;列表、集合、字典是可变数据类型 数字类型&#xff1a;int float boo complex复数 2.变量无需声明数据类型&#xff0c;且允许同时为多个变量…

二手手机行业商家如何利用二手机店erp进行破局?

在数字化和AI发展越发先进的的今天&#xff0c;二手手机市场正迎来前所未有的变革。途渡科技精心打造的超机购ERP管理软件&#xff0c;凭借其独特的智能化、高效化特点&#xff0c;正在引领这场变革&#xff0c;为二手手机商家提供全面、深度的数字化管理解决方案。二手手机商家…

软件设计师笔记和错题

笔记截图 数据库 模式是概念模式 模式/内模式 存在概念级和内部级之间&#xff0c;实现了概念模式和内模式的互相转换 外模式/模式映像 存在外部级和概念级之间&#xff0c;实现了外模式和概念模式的互相转换。 数据的物理独立性&#xff0c; 概念模式和内模式之间的映像…

Java开发大厂面试第03讲:线程的状态有哪些?它是如何工作的?

线程&#xff08;Thread&#xff09;是并发编程的基础&#xff0c;也是程序执行的最小单元&#xff0c;它依托进程而存在。一个进程中可以包含多个线程&#xff0c;多线程可以共享一块内存空间和一组系统资源&#xff0c;因此线程之间的切换更加节省资源、更加轻量化&#xff0…

微信小程序踩坑,skyline模式下,scroll-view下面的一级元素设置margin中的auto无效,具体数据有效

开发工具版本 基础库 开启skyline渲染调试 问题描述 skyline模式下,scroll-view下面的一级元素的margin写auto的值是没有效果的(二级元素margin写auto是有效果的),关闭这个模式就正常显示 演示效果图 父元素的宽度和高度效果(宽度是750rpx,宽度占满的) 一级元素宽度和css效果…

Apifox:API 接口自动化测试完全指南

01 前言 这是一篇关于 Apifox 的接口自动化测试教程。相信你已经对 Apifox 有所了解&#xff1a;“集 API 文档、API 调试、API Mock、API 自动化测试&#xff0c;更先进的 API 设计/开发/测试工具”。 笔者是后端开发&#xff0c;因此这篇教程关注的是 API 自动化测试&#…

Jenkins 忘记登录密码怎么办

在安装Jenkins中遇到忘记登录密码该怎么呢&#xff1f;下面是一个解决办法 1. 先停止jenkins服务 我是用tomcat启动的jenkis 2. 找到config.yaml文件 find / -name config.xml命令执行后找到如下结果&#xff1a; /root/.jenkins/config.xml /root/.jenkins/users/admin_839…