【第一章 - 绪论】- 数据结构(近八千字详解)
目录
一、 数据结构的研究内容
二、基本概念和术语
2.1 - 数据、数据元素、数据项和数据对象
2.2 - 数据结构
2.2.1 - 逻辑结构
2.2.2 - 存储结构
2.3 - 数据类型和抽象数据类型
三、抽象数据类型的表现与实现
四、算法和算法分析
4.1 - 算法的定义及特性
4.2 - 评价算法优劣的基本标准
4.3 - 算法的时间复杂度
4.3.1 - 问题规模和语句频度
4.3.2 - 算法的时间复杂度定义
4.3.3 - 算法的时间复杂度分析举例
4.3.4 - 最好、最坏和平均时间复杂度
4.4 - 算法的空间复杂度
参考资料:数据结构(C 语言版 | 第二版) - 严蔚敏 李冬梅 吴伟民 编著
一、 数据结构的研究内容
早期的计算机主要用于数值计算,现在,计算机主要用于非数值计算,包括处理字符、表格和图像等具有一定结构的数据。这些数据内容存在着某种联系,只有分清楚数据的内在联系、合理地组织数据,才能对它们进行有效地处理,设计出高效的算法。如何合理地组织数据、高效地处理数据,这就是"数据结构"主要研究的问题。
-
计算机主要用于数值计算时,一般要经过如下几个步骤:
-
首先从具体问题抽象出数学模型。
寻求数学模型的实质是分析问题,从中提取操作的对象,并找出这些操作对象之间的关系,然后用数学语言加以描述,即建立相应的数学方操。
-
然后设计一个解此数学模型的算法。
求解这些数学方程的算法是计算数学研究的范畴,如高斯消元法、差分法、有限元法等算法。
-
最后编写程序,进行测试、调试、直到解决问题。
-
-
数据结构主要研究非数值计算问题,非数值计算问题的数学模型不再是数学方程,而是诸如线性表、树和图的数据结构。因此简单来说,数据结构是一门研究非数值计算程序中的操作对象,以及这些对象之间的关系和操作的学科。
下面通过三个实例加以说明:
-
例 1 - 学生学籍管理系统:
表 1.1 学生基本信息表:
学号 姓名 性别 籍贯 专业 060214201 杨阳 男 安徽 计算机科学与技术 060214202 薛林 男 福建 计算机科学与技术 060214215 王诗萌 女 吉林 计算机科学与技术 060214216 冯子晗 女 山东 计算机科学与技术 操作对象:每个学生的基本信息。
操作对象之间的关系:一对一的线性关系。
操作:查找、插入和删除等。
数据结构:线性表。
-
例 2 - 人机对弈问题:
图 1.1 井字棋的对弈树:

操作对象:各种棋盘格局。
操作对象之间的关系:一对多的层次关系。
操作:查找、插入和删除等。
数据结构:树。
-
例 3 - 最短路径问题:
图 1.2 最短路径问题:

操作对象:图中的顶点。
操作对象之间的关系:多对多的网状关系。
操作:查找、插入和删除等。
数据结构:图。
-
二、基本概念和术语
2.1 - 数据、数据元素、数据项和数据对象
数据(Data)是客观事物的符号表示,是所有能输入到计算机中被计算机程序处理的符号的总称。
数据元素(Data Element)是数据的基本单位,在计算机中通常作为一个整体进行考虑和处理。在有些情况下,数据元素也称为元素、记录等。数据元素用于完整地描述一个对象,如示例中的一名学生记录、树中棋盘的一个格局(状态),以及图中的一个顶点等。
数据项(Data Item)是组成数据元素的、有独立含义的、不可分割的最小单位。
数据对象(Data Object)是性质相同的数据元素的集合,是数据的一个子集。

2.2 - 数据结构
数据结构(Data Structure)是相互之间存在一种或多种特定关系的数据元素的集合。
同样的数据元素,可以组成不同的数据结构;不同的数据元素,可以组成相同的数据结构。
数据结构包括逻辑结构和存储结构两个层次。
2.2.1 - 逻辑结构
数据的逻辑结构是从逻辑关系上描述数据,它与数据的存储无关,是独立于计算机的。因此,数据的逻辑结构可以看作是从具体问题抽象出来的数学模型。
根据数据元素之间关系的不同特性,通常有四类基本逻辑结构,如下图所示,它们的复杂程度依次递进。
集合结构:数据元素之间除了"属于同一集合"的关系外,别无其他关系。
其中集合结构、树结构和图结构都属于非线性结构。
2.2.2 - 存储结构
数据对象在计算机中的存储表示称为数据的存储结构,也称为物理结构。把数据对象存储到计算机时,通常要求既要存储各数据元素的数据,又要存储数据元素之间的逻辑关系,数据元素在计算机内用一个结点(node)来表示。
逻辑结构是具体问题抽象出来的数学模型,存储结构是逻辑结构在计算机中的存储表示。
数据元素在计算机中有两种基本的存储结构,分别是顺序存储结构和链式存储结构。
-
顺序存储结构是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系,通常借助程序设计语言中的数组类型来描述。
-
顺序存储结构要求所有的元素依次存放在一片连续的存储空间中,而链式存储结构,无需占用一整块存储空间,但为了表示结点之间的关系,需要给每个结点附加指针字段,用于存放后续元素的存储地址。所以链式存储结构通常借助于程序设计语言的指针类型来描述。
2.3 - 数据类型和抽象数据类型
数据类型(Data Type)是高级程序设计语言中的一个基本概念,前面提到过顺序存储结构可以借助程序设计语言的数组类型描述,链式存储结构可以借助指针类型描述,所以数据类型和数据结构的概念密切相关。
一方面,在程序设计语言中,每一个数据都属于某种数据类型。类型明显或隐含地规定了数据的取值范围、存储方式以及允许进行的运算,数据类型是一个值的集合和定义在这个值集上的一组操作的总称。C 语言除了提供整型、实型、字符型等基本类型数据,还允许用户自定义各种类型数据,例如数组、结构体和指针等。
抽象数据类型(Abstract Data Type,ADT)一般指用户定义的、表示应用问题的数学模型,以及定义在这个模型上的一组操作的总称,具体包括三部分:数据对象、数据对象上关系的集合,以及对数据对象的基本操作的集合。
三、抽象数据类型的表现与实现
抽象数据类型的概念与面向对象方法的思想是一致的。抽象数据类型独立于具体实现,将数据和操作封装在一起,使得用户程序只能通过抽象数据类型定义的某些操作来访问其中的数据,从而实现了信息隐藏。
四、算法和算法分析
程序 = 数据结构 + 算法
4.1 - 算法的定义及特性
算法(Algorithm)是为了解决某类问题而规定的一个有限长的操作序列。
一个算法必须满足以下五个重要特性:
-
有穷性:一个算法必须总是在执行有穷步后结束,且每一步都必须在有穷时间内完成。
-
确定性。
-
可行性。
-
输入:一个算法有零个或多个输入。
-
输出:一个算法有一个或多个输出。
4.2 - 评价算法优劣的基本标准
一个算法的优劣应该从以下几个方面来评价:
-
正确性。
-
可读性。
-
健壮性(鲁棒性,Robustness):当输入的数据非法时,好的算法能适当地做出正确反应或进行相应处理,而不会产生一些莫名其妙的输出结果。
-
高效性:高效性包括时间和空间两个方面。时间高效是指算法设计合理,执行效率高,可以用时间复杂度来度量;空间高效是指算法占用存储容量合理,可以用空间复杂度来度量。时间复杂度和空间复杂度是衡量算法的两个主要指标。
4.3 - 算法的时间复杂度
如何评估算法时间开销?
-
让算法先运行,事后统计运算时间。
不过这种方法的缺陷很显然:
-
统计结果和机器性能有关。
-
统计结果和编程语言有关,越高级的语言执行效率越低。
-
统计结果和编译程序产生的机器指令质量有关。
-
有些算法是不能事后再统计的,比如导弹控制算法。
-
-
因此我们通常采用事前分析估算法,通过计算算法的渐进时间复杂度来衡量算法的效率。
4.3.1 - 问题规模和语句频度
不考虑计算机的软硬件等环境因素,影响算法时间代价的最主要因素是问题规模。问题规模是算法求解问题输入量的多少,是问题大小的本质表示,一般用整数 n 表示。问题规模 n 对不同的问题含义不同。显然 n 越大算法的执行时间越长。
一个算法的执行时间大致等于所有语句执行时间的总和,而语句的执行时间则为该条语句的重复执行次数和执行一次所需时间的乘积。
一个语句的重复执行次数称作语句频度(Frequency Count)。
由于语句的执行要由源程序经编译程序翻译成目标代码,目标代码经配装再执行,因此语句执行一次实际所需的具体时间是与机器的软、硬件环境(如机器速度、编译程序质量等)密切相关的。所以,所谓的算法分析并非精确统计算法实际执行所需时间,而是针对算法中语句的执行次数做出估计,从中得到算法执行时间的信息。
设每条语句执行一次所需的时间均是单位时间,则一个算法的执行时间可用该算法中所有语句频度之和来度量。
例 - 求 1 + 2 + ... + n:
sum = 0; // 语句频度为 1
for (int i = 1; i <= n; ++i) // 语句频度为 n + 1,当 i == n + 1 时,还要判断一次
{sum += i; // 语句频度为 n
}
该算法中所有语句频度之和是一个关于 n 的函数,用 f(n) 表示之。换句话说,上例算法的执行时间与 f(n) 成正比。
f(n) = 2n + 2。
4.3.2 - 算法的时间复杂度定义
对于简单的算法,可用直接计算出算法中所有语句的频度,但是对于稍微复杂一些的算法,则通常是比较困难的,即便能够给出,也可能是一个非常复杂的函数。因此,为了客观地反映一个算法的执行时间,可以只用算法中的"基本语句"的执行次数来度量算法的工作量。
所谓"基本语句"指的是算法中重复执行次数和算法的执行时间成正比的语句,它对算法运行时间的贡献最大。
通常,算法的执行时间是随问题规模增长而增长的,因此对算法的评价通常只需考虑其随问题规模增长的趋势。这种情况下,我们只需要考虑当问题规模充分大时,算法中基本语句的执行次数在渐进意义下的阶。如上面例题中求 1 + 2 + ... + n 的算法,当 n 趋向无穷大时,显然有:,即当 n 充分大时,f(n) 和 n 之比是一个不等于零的常数。即 f(n) 和 n 是同阶的,或者说 f(n) 和 n 的数量级(Order of Magnitude)相同。在这里,我们用 "O" 来表示数量级,记作 T(n) = O(f(n)) = O(n)。
由此我们可以给出下述算法时间复杂度的定义:
一般情况下,算法中基本语句重复执行的次数是问题规模 n 的某个函数 f(n),算法的时间度量记作 T(n) = O(f(n)),它表示随问题规模 n 的增大,算法执行时间的增长率和 f(n) 的增长率相同,称作算法的渐进时间复杂度,简称时间复杂度(Time Complexity)。
4.3.3 - 算法的时间复杂度分析举例
分析算法时间复杂度的基本方法为:找出所有语句中语句频度最大的那条语句作为基本语句,计算基本语句的频度得到问题规模的某个函数 f(n),取其数量级用符号 "O" 表示即可。具体计算数量级时,可以遵循以下定理:
上述定理说明,在计算算法时间复杂度时,可以忽略所有低次幂项和最高次幂的系数,这样可以简化算法分析,也体现出了增长率的含义。
下面举例说明如何求非递归算法的时间复杂度。
-
例 1:
void func1(int n) {int cnt = 0;for (int i = 0; i < 100; ++i){++cnt;}printf("%d\n", cnt); }如果算法的执行时间不随问题规模 n 的增加而增长,算法中语句频度就是某个常数,即便这个常数再大,算法的时间复杂度都是 O(1)。
-
例 2:
void func2(int n) {int cnt = 0;for (int i = 0; i < 2 * n; ++i){++cnt;}int m = 10;while (m--){++cnt;}printf("%d\n", cnt); }时间复杂度为 O(n)。
-
例 3:
void func3(int n, int m) {int cnt = 0;for (int i = 0; i < n; ++i){++cnt;}for (int i = 0; i < m; ++i){++cnt;}printf("%d\n", cnt); }时间复杂度为 O(n + m)。
若提示 n 远大于 m,或者 m 远大于 n,时间复杂度则为 O(n) 或 O(m)。
-
例 4:
void func4(int n) {int cnt = 0;for (int i = 0; i < n; ++i){for (int j = 0; j < n; ++j){++cnt;}}for (int i = 0; i < 2 * n; ++i){++cnt;}int m = 10;while (m--){++cnt;}printf("%d\n", cnt); }时间复杂度为 O(n^2)。
若算法可用递归方法描述,则算法的时间复杂度通常可使用递归方程表示,此时将涉及递归方程求解问题。
-
例 1 - 计算阶乘递归算法的时间复杂度:
long long factorial(size_t n) {if (n == 0 || n == 1)return 1;return n * factorial(n - 1); }因为 n 的阶乘仅比 n - 1 的阶乘多一次乘法运算,即 factorial = n * factorial(n - 1),那么有:f(n) = 1 + f(n - 1) = 2 + f(n - 2) = ... ... = n - 1 + f(1) = n,所以阶乘递归算法的时间复杂度为 O(n)。
-
例 2 - 计算斐波那契递归算法的时间复杂度:
long long fibonacci(size_t n) {if (n == 0)return 0;else if (n == 1 || n == 2)return 1;elsereturn fibonacci(n - 1) + fibonacci(n - 2); }分析(以 fib(6) 为例):

因此斐波那契递归算法的时间复杂度为 O(2^n)。
4.3.4 - 最好、最坏和平均时间复杂度
对于某些问题的算法,其基本语句的频度不仅仅与问题的规模相关,还依赖于其他因素。
下面通过一个示例说明:
const char* my_strchr(const char* str, int character)
{while (*str != '\0'){if (*str == character){return str;}str++;}return NULL;
}
容易看出,此算法中 if 语句的频度不仅与问题规模 n 有关,还与
str和character有关。假设
str指向的字符串中必定存在字符character,则查找必定成功,且 if 语句的频度将由字符第一次出现在字符串中的位置决定。此例说明,算法的时间复杂度不仅与问题的规模有关,还与问题的其他因素有关。再如某些排序的算法,其执行时间与待排序记录的初始状态有关。因此,有时会对算法有最好、最坏以及平均时间复杂度的评价。
称算法在最好情况下的时间复杂度为最好时间复杂度,指的是算法计算量可能达到最小值;称算法在最坏情况下的时间复杂度为最坏时间复杂度,指的是算法计算量可能达到的最大值;算法的平均时间复杂度是指算法在所有可能情况下,按照输入实例以等概率出现时,算法计算量的加权平均值。
对算法时间复杂度的度量,人们更关心的是最坏情况下和平均情况下的时间复杂度。然而在很多情况下,算法的平均时间复杂度难于确定,因此,通常只讨论算法在最坏情况下的时间复杂度,即分析最坏情况下,算法执行时间的上界。
-
例 1 - 计算冒泡排序算法的时间复杂度:
写法一:
void bubble_sort(int arr[], int sz) {for (int i = 0; i < sz - 1; ++i) // 进行 sz - 1 趟冒泡排序{int exchange = 0; // 假设待排序数组已经有序for (int j = 0; j < sz - 1 - i; ++j) // 每趟冒泡排序比较 sz - 1 - i 对{if (arr[j] > arr[j + 1]) // 升序{int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;exchange = 1;}}if (exchange == 0){break;}} }写法二:
void bubble_sort(int arr[], int sz) {for (int end = sz - 1; end > 0; --end) {int exchange = 0;for (int i = 0; i < end; ++i) // 确定第 end 位{if (arr[i] > arr[i + 1]){int tmp = arr[i];arr[i] = arr[i + 1];arr[i + 1] = tmp;exchange = 1;}}if (exchange == 0){break;}} }最好时间复杂度为 O(n),最坏时间复杂度为 O(n^2)。
-
例 2 - 计算二分查找算法的时间复杂度:
int binary_search(int arr[], int sz, int target) {int left = 0;int right = sz - 1;while (left <= right){int mid = left + ((right - left) >> 1); if (arr[mid] < target){left = mid + 1;}else if (arr[mid] > target){right = mid - 1;}else{return mid;}}return -1; }最好时间复杂度为 O(1)。
假设总共有 n 个元素,每次查找的区间大小就是 n,n/2,n/4,...,n/2^k,其中 k 表示循环的次数,在最坏情况下有 n/2^k = 1,即 k = log2(n),它是以 2 为底 n 的对数,所以最坏时间复杂度为 O(log2(n)),简写为 O(logn)。
注意:以其他数为底数的对数不能简写。
4.4 - 算法的空间复杂度
关于算法的存储空间需求,类似于算法的时间复杂度,我们采用渐近空间复杂度作为算法所需存储空间的度量,简称空间复杂度(Space Complexity),它也是问题规模 n 的函数,记作:S(n) = O(f(n))。
一般情况下,一个程序在机器上执行时,除了需要寄存本身所用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的辅助存储空间。其中,对于输入数据所占的具体存储量取决于问题本身,与算法无关,这样只需分析该算法在实现时所需要的辅助空间就可以了。
若算法执行时所需要的辅助空间相对于输入数据量而言是个常数,则称这个算法为原地工作,辅助空间为 O(1)。
-
例 1 - 数组逆序,将一维数组
nums中的numsSize个数逆序存放到原数组中:算法一:
void reverse1(int* nums, int numsSize) {for (int i = 0; i < numsSize / 2; ++i){int tmp = nums[i];nums[i] = nums[numsSize - 1 - i];nums[numsSize - 1 - i] = tmp;} }算法一仅需要另外借助两个变量
i和tmp,与问题规模 n 大小无关,所以其空间复杂度为 O(1)。算法二:
void reverse2(int* nums, int numsSize) {int* tmp = (int*)malloc(sizeof(int) * numsSize);if (NULL == tmp){perror("malloc failed!");return;}for (int i = 0; i < numsSize; ++i){tmp[i] = nums[numsSize - 1 - i];}for (int i = 0; i < numsSize; ++i){nums[i] = tmp[i];}free(tmp);tmp = NULL; }算法二需要另外借助一个大小为
numsSize的辅助数组 b,所以其空间复杂度为 O(n)。 -
例 2 - 计算斐波那契递归算法的空间复杂度(重要):
long long fibonacci(size_t n) {if (n == 0)return 0;else if (n == 1 || n == 2)return 1;elsereturn fibonacci(n - 1) + fibonacci(n - 2); }递归算法的空间复杂度 = 每次递归的空间复杂度 * 递归深度。
因此斐波那契递归算法的空间复杂度为 O(n)。
对于一个算法,其时间复杂度和空间复杂度往往是相互影响的,当追求一个较好的时间复杂度时,可能会导致占用较多的存储空间,即可能会使空间复杂度的性能变差,反之亦然。不过经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度,所以,人们都以算法的时间复杂度作为算法优劣的衡量指标。
相关文章:
【第一章 - 绪论】- 数据结构(近八千字详解)
目录 一、 数据结构的研究内容 二、基本概念和术语 2.1 - 数据、数据元素、数据项和数据对象 2.2 - 数据结构 2.2.1 - 逻辑结构 2.2.2 - 存储结构 2.3 - 数据类型和抽象数据类型 三、抽象数据类型的表现与实现 四、算法和算法分析 4.1 - 算法的定义及特性 4.2 - 评价…...
QIfw制作软件安装程序
前言 Qt Installer Framework是Qt默认包的发布框架。它很方便,使用静态编译Qt制作而成。从Qt的下载地址中下载Qt Installer Framework,地址是:http://download.qt.io/official_releases/qt-installer-framework/ 。支持我们自定义一些我们需要的东西包括页面、交互等。 框…...
【C++】C++入门(上)
前言: C是在C语言的基础上不断添加东西形成的一门语言,在C语言的基础上引入了面向对象的思想。因此C既是面向对象的语言,也是面向过程的语言。因为C是以C语言为基础的,所以基本上C兼容所有的C语言。目前最常用的版本是C98和C11这两…...
5. Kimball维度建模常用术语及概念(一)
文章目录维度建模过程相关概念1. 收集业务需求与数据实现2. 协作维度建模研讨3. 四步骤维度设计过程4. 业务过程5. 粒度6. 描述环境的维度7. 用于度量的事实8. 维度模型事实表技术术语1. 事实表结构2. 可加、半可加、不可加事实3. 事实表中的空值4. 一致性事实5. 事务事实表6. …...
内核调试之Panic-Oops日志分析
这部分我们接着之前的思考,看看内核异常日志的分析。 1 Panic 调试 2 Oops调试 内核出现Panic或Oops错误,如何分析定位问题原因? 首先,保留现场,如下所示为一次非法虚拟地址访问错误。 EXT4-fs (sdc3): recovery c…...
论文解读 | [AAAI2020] 你所需要的是边界:走向任意形状的文本定位
目录 1、研究背景 2、研究的目的 3、方法论 3.1 Boundary Point Detection Network(BPDN) 3.2 Recognition Network 3.3 Loss Functions 4、实验及结果 论文连接:https://ojs.aaai.org/index.php/AAAI/article/view/6896 1、研究背景 最近,旨在…...
数据挖掘流程简单示例10min
数据挖掘流程简单示例10min 套路: 准备数据实现算法测试算法 任务1:亲和性分析 如果一个顾客买了商品X,那么他们可能愿意买商品Y衡量方法: 支持度support : 所有买X的人数 置信度confidence : 所有买X和Y的人数所有买X的人数…...
KDJB1200六相继电保护测试仪
一、概述 KDJB1200继电保护测试仪是在参照电力部颁发的《微机型继电保护试验装置技术条件(讨论稿)》的基础上,广泛听取用户意见,总结目前国内同类产品优缺点,充分使用现代新的的微电子技术和器件实现的一种新型小型化微机继电保护测试仪。可…...
从WEB到PWA 开发-发布-安装
见意如题!本文主要来说说PWA开发!作为一个前端程序员,在没有任何Android/IOS的开发情况下,想想我们有多少种方法来开发一个原生移动应用程序!我们可以有非原生、混合开发,PWA等等手段。类似uniappÿ…...
FPGA纯vhdl实现MIPI CSI2 RX视频解码输出,OV13850采集,提供工程源码和技术支持
目录1、前言2、Xilinx官方主推的MIPI解码方案3、纯Vhdl方案解码MIPI4、vivado工程介绍5、上板调试验证6、福利:工程代码的获取1、前言 FPGA图像采集领域目前协议最复杂、技术难度最高的应该就是MIPI协议了,MIPI解码难度之高,令无数英雄竞折腰…...
《NFL橄榄球》:卡罗来纳黑豹·橄榄1号位
卡罗来纳黑豹(英语:Carolina Panthers)是一支位于北卡罗来纳州夏洛特的职业美式橄榄球球队。他们是国家美式橄榄球联合会的南区其中一支球队。他们与杰克逊维尔美洲虎在1995年加入NFL,成为扩充球队。 2018年球队市值为23亿美元&am…...
我说我为什么抽不到SSR,原来是这段代码在作祟...
本文是龚国玮所写,熊哥有所新增修改删减,原文见文末。 我说我为什么抽不到SSR,原来是加权随机算法在作祟 阅读本文需要做好心理准备,建议带着深究到底的决心和毅力进行学习! 灵魂拷问 为什么有 50% 的几率获得金币&a…...
MySQL MGR 集群新增节点
前言 服务器规划现状(CentOS7.x) IP地址主机名部署角色192.168.x.101mysql01mysql192.168.x.102mysql02mysql192.168.x.103mysql03mysql192.168.x.104proxysql01proxysql、keepalived192.168.x.105proxysql02proxysql、keepalived 新增服务器IP&#x…...
【单目标优化算法】蜣螂优化算法(Dung beetle optimizer,DBO)(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
【C++】类和对象入门必知
面向过程和面向对象的初步认识类的引入类的定义类的访问限定符封装类的作用域类的实例化类对象模型this指针C语言和C实现Stack的对比面向过程和面向对象的初步认识 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解…...
day38 动态规划 | 509、斐波那契数 70、爬楼梯 746、使用最小花费爬楼梯
题目 509、斐波那契数 斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n - 1) F(n - 2),其…...
2023年备考软考必须知道的6件事
不知不觉,距离2023年上半年软考也只有不到100天的时间了,报名入口也将在3月13日正式开通,你是正在犹豫是否参加考试? 还是已经开始着手准备复习? 关于软考考试你还有哪些疑问? 2023年备考软考必须知道的6件事,建议收藏…...
GLOG如何控制输出的小数点位数
1 问题 在小白的蹩脚翻译演绎型博文《GLOG从入门到入门》中,有位热心读者提问说:在保存日志时,浮点型变量的小数位数如何设置? 首先感谢这位“嘻嘻哈哈的地球人”赏光阅读了小白这不太通顺的博客文章,并提出了一个很…...
2022年全国职业院校技能大赛(中职组)网络安全竞赛试题A(6)
目录 模块A 基础设施设置与安全加固 一、项目和任务描述: 二、服务器环境说明 三、具体任务(每个任务得分以电子答题卡为准) A-1任务一:登录安全加固(Windows) 1.密码策略 a.密码策略必须同时满足大小…...
Safety-Gym环境配置与安
官网: https://github.com/openai/safety-gym https://github.com/openai/safety-starter-agents 一、安装依赖环境配置 建议使用python 3.7及以下环境,因为官方的safety-rl是基于tensorflow1.13.1实现,而tensorflow1.13.1只能支持python…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
ArcGIS Pro+ArcGIS给你的地图加上北回归线!
今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等,设置经线、纬线都以10间隔显示。 2、需要插入背会归线…...
用 FFmpeg 实现 RTMP 推流直播
RTMP(Real-Time Messaging Protocol) 是直播行业中常用的传输协议。 一般来说,直播服务商会给你: ✅ 一个 RTMP 推流地址(你推视频上去) ✅ 一个 HLS 或 FLV 拉流地址(观众观看用)…...
