目录

注:

一些概念和术语

1. 什么是数据结构?

逻辑结构

存储结构

数据类型和抽象数据类型

抽象数据类型的表示和实现

2. 什么是算法,什么是算法分析?

算法的定义及特性

评价算法优劣的基本标准

算法的时间复杂度

算法的空间复杂度


注:

本视频参考:B站up 鹏哥C语言的视频

《 数据结构(C语言版)》


一些概念和术语

Wirth教授曾说:算法 + 数据结构 = 程序

名称 意义 举例

数据

是客观事物的符号表示,是所有能输入到计算机程序处理的符号的总称。 整数、实数、字符串等等。

数据元素

是数据的基本单位,在计算机中通常作为一个整体进行考虑和处理。

图中的一个顶点、一名学生的记录等等。
数据项 是组成数据元素的、有独立意义的、不可分割的最小单位。 学生基本信息表中的学号、姓名等等。
数据对象 是性质相同的数据元素的集合,是数据的一个子集。 整数数据对象是一个集合N = {0, ±1, ±2, …}等。

1. 什么是数据结构?

数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。

从现有的各种实例(诸如:最短路径、井字棋等等)中,我们也可以看出,数据结构主要研究的是非数值计算程序设计中的操作对象,以及对象间的关系和操作。

数据结构包括两个层次:逻辑结构和存储结构。

逻辑结构

特点:

  • 从逻辑关系上描述数据。
  • 与数据的存储无关。
  • 是独立于计算机的。

由上述的三个特点我们可以得出一个观点:数据的逻辑结构可以看作是从具体问题抽象出来的数学模型。

数据的逻辑结构由两个要素构成:

  1. 数据元素
  2. 关系(即数据元素之间的逻辑关系)

而这两个概念又会因为数据元素关系间的不同发展出不同的特性,这就是四类基本结构:集合结构、线性结构、树结构以及图结构。

集合结构

最好的例子就是学生与班级的关系:假设在刚刚入学时,一名学生与班上其他任何同学都没有关系,那么此时这名同学与其他同学之间唯一的联系,就是 “我们同属于一个班级” 这个概念。

线性结构

例如:学生信息数据按照其入学报到的时间先后顺序进行排列,将组成一个线性结构。

树结构

例如:在班级的管理层中,班长管理多个组长,组长管理多个组员,从而形成了树形结构。

图结构或网状结构

例如:多为同学之间相互交流,其中任何两位同学都可以是朋友关系,这就构成了一个图结构(网状结构)。

在上述的结构中,只有树结构图结构属于非线性结构。如果将非线性结构整理起来,那么:

非线性结构 特点
具有多个分支的层次结构。
二叉树 具有两个分支的层次结构。
有向图 是一种图结构,边是顶点的有序对。
无向图 是另一种图结构,边是顶点的无序对。

那么与之相对的,有哪些属于线性结构呢?线性结构包括:

线性结构 特点
线性表 典型的线性结构,如我们经常填写的个人信息表。
栈和队列 具有特殊限制的线性表,数据操作只能在表的一端或者两端进行。
字符串 数据元素仅由一个字符组成,也是特殊的线性表。
数组 是线性表的推广,它的设数据元素就是一个线性表。
广义表 是线性表的推广,它的数据元素是一个线性表,但是不同构(即或者是单元素,或者是线性表)。

总结(参考《数据结构(C语言版)》):

存储结构

数据对象在计算机中的存储表示被称为数据的存储结构,也被称为物理结构

如果把数据对象存储到计算机中,一般的要求是:

  1. 存储各数据元素的数据。
  2. 存储数据元素之间的逻辑关系。

在计算机内,数据元素用一个结点表示。与逻辑结构相似,存储结构也有两种基本的存储结构,分别是:顺序存储结构和链式存储结构。

顺序存储结构

借助元素在存储其中的相对位置来表示数据元素之间的逻辑关系,通常借助程序设计语言的数组类型进行描述。

假设数据从地址为 0 处开始从低地址向高地址存储,每个节点占据50个存储单元。现在我们需要存储“学生基本信息表”上的信息,,此时一个节点就对应一个学生的信息记录,那么就可以有一个对应的顺序结构:

地址 学号 姓名 性别 籍贯 专业
0 00000001 小明 xxx 计算机科学与技术
50 00000002 小红 xxx 语文
100 00000003 李明 xxx 英语
150 00000004 李华 xxx 英语

链式存储结构

顺序存储结构要求所有的元素依次存放在一片连续空间内,而链式存储结构无需占用一整块存储空间。 尽管如此,为了链接各个存储节点(即表示节点之间的关系),需要给每个节点附加指针字段,用于存放后续元素的存储地址(参考:链表)。

所以,链式存储结构通常借助于程序设计语言的指针类型来描述。

相同地存储一张“学生信息基本表”上的信息,链式存储结构要求在每一个节点附加“下一个节点的地址”,即后续这种字段:

地址 学号 姓名 性别 籍贯 专业 后续节点的首地址
0 00000001 小明 xxx 计算机科学与技术 100
50 00000002 小红 xxx 语文 ^
100 00000003 李明 xxx 英语 150
150 00000004 李华 xxx 英语 50

数据类型和抽象数据类型

数据类型

在程序设计语言中,每一个数据都属于某种数据类型。数据类型规定了数据的取值范围、存储方式和允许进行的运算。

概念

  1. 是一个值的集合和都要在这个值集上一组操作的总称。
  2. 是高级程序设计语言中的一个基础概念。(譬如之前在顺序存储结构中出现的数组类型,在链式存储结构中出现的指针类型,这些都说明了数据类型这一概念的重要性)

例如:

C语言的整型变量,值集是某个区间上的整数(区间大小取决于机器),定义在其上的操作为加、减、乘、除和取模等算数计算。

抽象数据类型

抽象,就是抽取出实际问题的本质。

  • 汇编语言中存在的数据的十进制表示,就是在计算机中二进制表示的数据的抽象。
  • 而高级语言中存在的数据类型,如整型、实型、字符型等,就是更高一级的抽象。
  • 再利用高级语言中的这些类型,我们就能进一步构造出线性表、栈、队列、树、图等复杂的抽象数据类型。

概念: 一般指由用户定义的,表示应用问题的数学模型,以及定义在这个模型上的一组存在的总称。它的定义仅取决于它的一组逻辑顺序。

一个抽象数据类型包括:

  1. 数据对象
  2. 数据对象上关系的集合
  3. 对数据对象的基本操作的集合

抽象数据类型的定义格式

ADT 抽象数据类型名{

数据对象:        //数据对象的定义

数据关系:        //数据关系的定义

基本操作:        //基本操作的定义

}ADT 抽象数据类型名

其中,数据对象和数据关系的定义采用数学符号自然语言描述,而基本操作的定义格式为:

基本操作名 (参数表)

初始条件:        //初始条件描述

操作结果:        //操作结果描述

1. 基本操作的两种参数:

  • 赋值参数(只为操作提供输入值)
  • 引用参数(以“&”打头,除了提供输入值之外,还将返回操作结果)

2. “初始条件”描述的是操作执行前数据结构和参数应满足的条件。(初始条件可以为空,即省略)

3. “操作结果”说明操作正常完成后,数据结构的变化情况和应返回的结果。

抽象数据类型的表示和实现

抽象数据类型的使用,有助于模块化处理问题,在更高层次进行软件的分析和设计,提高软件的整体性能和利用率。

抽象数据类型和类的概念——面向对象方法的思想。

一个复数的例子(来自  《 数据结构(C语言版)》):

以“&”打头的参数即为引用参数。

(1)定义部分(ADT — 抽象数据类型):

ADT Complex {数据对象: D = { e1, e2| e1, e2 ∈ R, R是实数集 }数据关系: S = { <e1, e2>| e1 是复数的实部,e2 是复数的虚部}基本操作:Creat(&C, x, y)操作结果: 构造复数C,其实部和虚部分别被赋以参数和y的值。GetReal(C)初始条件: 复数C以存在。操作结果: 返回复数C的实部值。GetImag(C)初始条件: 复数C以存在。操作结果: 返回复数C的虚部值。ADD(C1, C2)初始条件: C1, C2是复数。操作结果: 返回两个复数C1和C2的和。Sub(C1, C2)初始条件: C1, C2是复数。操作结果: 返回两个复数C1和C2的差。
}ADT Complex

这就是抽象数据类型的定义。在C语言中,由于语言自身的限制,难以达到面向对象的语言那种精确的描述,但是我们依旧可以完成一部分的要求。就比如C语言需要通过声明一个不完整的类型才能完成一个抽象数据类型的封装。

(2)表示部分:

typedef struct            //复数类型
{float Realpart;       //实部float Imagepart;      //虚部
}Complex;

(3)实现部分:

void Create( &Complex C, float x, float y )
{ //构造一个复数C.Realpart = x;C.Imagepart = y;
}float GetReal( Complex C )
{ //取复数 C = x + yi 的实部return C.Realpart;
}float GetImag( Complex C )
{ //取复数 C = x + yi 的虚部return C.imagepart;
}Complex Add( Complex C1, Complex C2 )
{ // 求两个复数 C1 和 C2 的和sumComplex sum;sum.Realpart = C1.Realpart + C2.Realpart;sum.Imagepart = C1.Imagepart + C2.Imagepart;return sum;
}Complex Sub( Complex C1, Complex C2 )
{ //两个复数 C1 和 C2 的差differenceComplex difference;difference.Realpart = C1.Realpart - C2.Realpart;difference.Imagepart = C1.Imagepart - C2.Imagepart;return difference;
}

这样定义就可以在主程序调用Create函数构建一个复数,调用Add或者Sub函数实现复数的加减法了。

2. 什么是算法,什么是算法分析?

算法(Algorithm)就是定义良好的计算过程,它取一个或一组的值为输出,并产生一个或一组值作为输出。总之,算法就是一系列的计算步骤,用来将输入数据转化为输出结果。

在某一类型的数据结构上,总要涉及其上施加的运算。研究运算,才能清楚理解数据结构的定义和意义;联系数据,才能更好地涉及算法。为了描述某种操作,常常需要涉及算法,因而算法是研究数据结构的重要途经

算法的定义及特性

算法的定义:是为了解决某类问题而规定的一个有限长的操作序列。

算法的特性:

  1. 有穷性。一个算法必须在有穷步内结束,每一步必须在有穷时间内结束。
  2. 确定性。算法对 每种情况下应执行的操作 有明确的规定,且不会产生二义性,能使算法的执行者或者阅读者都能明确其含义和执行。
  3. 可行性。算法中的所有操作都可以通常已经实现的基本操作运算执行有限次来实现。
  4. 输入。一个算法有 零个 或者 多个 输入。当通过函数描述算法时,输入往往是形参的形式,当它们被调用时,从主调用函数获得输入值。
  5. 输出。一个算法有 一个 或者 多个 输出。输出是算法进行信息后获得的结果,无输出的算法是无意义的。当用函数描述算法时,输出多用返回值或引用类型的形参表示。

评价算法优劣的基本标准

一个算法的好坏应该从几个方面进行评价:

  1. 正确性。在合理的数据输入下,能够在有限的运行时间内得到正确的结果。
  2. 可读性。一个好的算法,首先应该便于人们的理解和相互交流,其次才是机器可执行性。
  3. 健壮性。当输入的数据非法时,好的算法能适当得做出正确反映或者进行相应的处理,而不是产生一些莫名其妙的输出结果。
  4. 高效性。高效性包括时间和空间两个部分。时间高效:指算法涉及合理,执行效率高,通过时间复杂度衡量。空间高效:指算法占有存储容量合理,用空间复杂度表示。(空间复杂度和时间复杂度是衡量算法的两个主要指标)

算法的时间复杂度

算法效率分析的目的:

  1. 确认算法实际可行。
  2. 若存在多个算法,衡量其在时间和空间上的性能差别,挑选出较优算法。

衡量算法效率的方法:事后统计法和事前分析估算法。

事后统计法需要先实现算法,再测量其时间和空间开销。这种方法存在明显缺陷:

一、必须把算法转换成可执行的程序。

二、时空开销的测量结果直接和计算机软硬件等环境因素挂钩,算法本身的优劣容易被忽略。

所以我们通常采用事前分析估算法,通过计算算法的渐进复杂度来衡量算法的效率。

问题规模和语句频率

概念:

  • 问题规模:在不考虑计算机的软硬件等环境因素的情况下,影响算法时间代价的最主要的因素就是问题规模。

问题规模作为算法求解问题输入量的多少,是问题大小的本质表示,一般用整数n表示。

例如:在排序运算中,n是参加排序的记录数;在矩阵运算中,n是矩阵的阶数;在树的有关运算中,n就是树的节点个数。

  • 语句频率:一条语句的重复执行次数被称为语句频率。
语句的执行时间 = 该条语句的重复执行次数 * 执行依次所需时间的乘积

由于代码的编译、装配和执行速度和机器的软、硬件环境密切相关,所以算法分析并非精确计算实际执行所需时间,而是估计算法中语句的执行次数,从而得到算法执行时间的信息。

例子:求两个n阶矩阵的乘积算法(题目来源:《 数据结构(C语言版)》)

条件:设每条语句执行所需的时间为单位时间,则一个算法的执行时间就可以用该算法中所有语句的频度之和来度量。

for(i = 1; i<= n; i++)                                //频度为 n + 1for(j = 1; j <= n; j++)                           //频度为 n * (n + 1)  注意:上一层循环中,第 n + 1 层循环是不会进入的。{c[i][j] = 0;                                  //频度为 n²for(k = 1; k<=n; k++)                         //频度为 n² * (n + 1)c[i][j] = c[i][j] + a[i][k] * b[k][j];    //频度为 n³}

用f(n)表示该算法中所有语句频度之和(即矩阵阶数n的函数),算法时间与f(n)成正比:

算法的时间复杂度定义

在上述的例子中,由于算法较为简单,我们可以通过这种方式计算出所有语句的频度,但如果算法较为复杂,那么上述的计算就会比较困难了。

因此,为了客观地反映一个算法的执行时间,可以只用算法中的 “基本语句” 的执行次数来度量算法的工作量。

基本语句的概念

所谓的 “基本语句” 指的是算法中重复执行次数和算法的执行时间成正比的语句,它对算法运行时间的贡献最大。

通常,算法的执行时间随着问题规模的增长而增长,因此对算法的评价通常只需考虑其随问题规模增长的趋势。这种情况下,我们只需考虑当问题规模充分大时,算法中基本语句的执行次数在渐进意义上的阶。如上述例子中,当 n 趋近于无穷大时,显然:

当n充分大时,f(n) 和 n³ 之比是一个不等于零的常数(即 f(n) 和 n³ 同阶)。在这里,我们用“O”来表示数量级,记作 T(n) = O(f(n)) = O(n³) 。

时间复杂度的定义:

一般情况下,算法中基本语句重复执行的次数是问题规模n的某个函数f(n),算法的时间量度记作

它表示随问题规模n的增大,算法执行时间的增长率和 f(n) 是增长率相同,称作算法的渐进时间复杂度,简称时间复杂度(Time Complexity)。

“O” 的严格定义

若T(n) 和 f(n)是定义在正整数集合上的两个函数,则T(n) = O(f(n))表示存在正的 常数C和 n1 ,使得当 n≥n1 时能满足 0 ≤ T(n) ≤ Cf(n) 。

算法的时间复杂度分析举例

分析时间复杂度的基本方法:

  1. 找出所有语句中语句频度最大的那条语句作为基本语句。
  2. 计算基本语句的频度得到问题规模n的某个函数f(n),取其数量级用符号“O”表示即可。

计算数量级时,可以遵循以下定理:

上述定理忽略了底层幂项和最高次幂的系数,简化了计算。

ps:还有关于递归算法的时间复杂度分析方法将在之后给出。

例子

常量阶示例:

{
x++;
s = 0;
}

此时两条语句频度均为1(与问题规模n无关),时间复杂度T(n) = O(1),被称为常量阶。

若算法的执行时间不随问题规模n的增加而增长,算法中的语句频度就会是某一常数。而只要是常数,对应的算法的时间复杂度就都是O(1)。

如:

for( i = 0; i<10000; i++ )
{x++;s = 0;
}

这个for循环实际上就只是 i 从 0 加到 10000 的计算。所以该算法的时间复杂度依旧是O(1)。


线性阶示例:

for( i = 0; i < n; i++ )
{x++;s = 0;
}

这个循环体涉及到了数据规模n,循环体内的两条语句频度均是f(n),算法的时间复杂度就是T(n) = O(n),即线性阶。


平方阶示例:

(1)  x = 0; y = 0;
(2)  for(k = 1; k <= n; k++)
(3)      x++;
(4)  for(i = 1; i <= n; i++)
(5)      for(j = 1; j <= n; j++)
(6)          y++;

根据之前的判断规则,只考虑程序段中频度最大的语句,即(6),频度为f(n) = n²,故该算法的时间复杂度为T(n) = O(n²),即平方阶。


立方阶示例:

(1)  x = 1;
(2)  for( i = 1;  i<=n; i++ )
(3)      for( j = 1; j <= i; j++ )
(4)          for( k = 1; k <=j; k++ )
(5)              x++;

取最大频度语句(5),由内向外计算语句(5)的执行次数,可得:

最终算得时间复杂度为T(n) = O(n³),称为立方阶。


对数阶示例:

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

设循环体内两条语句的频度均为f(n),则有:

所以算法的时间复杂度为

这就是对数阶。


常见的时间复杂度按照数量级递增排列,可得:

注意:不同的数量级的时间复杂度都有各自的优势区间,并没有哪一种一定是最好的选择。

最好、最坏和平均时间复杂度

例:在一堆数组a中顺序查找某个值等于e的值,并返回其所在位置。

(1)  for( i = 0; i < n; i++ )
(2)      if(a[i] == e)return i + 1;
(3)  return 0;

假设:在 数组a 中必定存在值等于 e 的元素。

在这个算法中,语句(2)的频度不仅与问题规模n有关,还与输入实例中的 数组a 中各元素的值及 e 的取值有关。

那么现在就存在三种情况:

  1. 假设 数组a 的各个元素值均为 e ,那么无论问题规模有多大,语句(2)的频度都是 f(n) = 1。
  2. 假设 数组a 中元素值为 e 的那个值是 数组a 最后的元素,那么语句(2)的频度就是 f(n) = n。
  3. 考虑剩余的大多数情况,不妨假设 数组a 中每个元素的值为 e 的概率是相同的,那么按照期望,语句(2)的频度应该是 f(n) = n/2。

总结:这个例子告诉我们,算法的时间复杂度不仅跟数据规模有关,还和问题的其他因素有关(还有些算法,其执行时间和待排序记录的初始状态有关)。因此,有时会对算法有最好、最坏和平均时间复杂度的评价。

  • 最好时间复杂度:算法计算量可能达到的最小值。
  • 最坏时间复杂度:算法计算量可能达到的最大值。
  • 平均时间复杂度:算法在所有可能情况下,按照输入实例以等概率出现时,算法计算量的加权平均值。

在通常情况下,最坏时间复杂度会得到更多关注,即分析在最坏情况下,算法执行的上界。

算法的空间复杂度

类似于时间复杂度,在计算算法的存储空间需求时,我们采用渐进空间复杂度作为算法所需存储空间的量度,简称空间复杂度(Space Complexity)。它也是问题规模n的函数,记作:

一般情况下,程序运作时除了指令、常数、变量和输入数据需要空间外,还需要一些辅助存储空间用来进行数据操作。其中,输入数据所占具体存储量取决于问题本身,与算法无关,这样我们就只要分析辅助存储空间即可

若算法执行时所需辅助空间相对于输入数据量而言是个常数,则称这个算法为原地工作,辅助空间为O(1)。除此之外,还有的算法需要占用的临时工作单元数与问题规模n有关。

示例

【算法1】

for( i = 0; i < n/2; i++ )
{t = a[i];a[i] = a[n - i - 1];a[n - i - 1] = t;
}

【算法2】

for( i = 0; i < n; i++ )
{b[i] = a[n - i - 1];
}
for( i = 0; i < n; i++ )
{a[i] = b[i];
}

分析:

这两个算法的结果是一样的,但是:

  1. 算法1仅需要借助一个变量t,与问题规模n的大小是无关的,所以空间复杂度为O(1)。
  2. 算法2需要借助一个大小为n的辅助数组b,所以其空间复杂度为O(n)。

时间复杂度和空间复杂度往往会互相影响,一方较好时,另一方就会较坏。但是通常情况下运算空间都是较为充足的,所以人们都偏向通过时间复杂度评价算法。

数据结构入门1(认识数据结构)相关推荐

  1. 【数据结构入门篇】数据结构与算法同我一起从入门开始,到入土为止

    前言 这一篇的发布就意味着我的数据结构专栏开始更新了,从最基础的开始入门,之后按顺序把每一个该学习的知识都总结一遍,复习巩固. 无论你是学过了还是准备开始学习,都可以一起.学过了你可以复习巩固,没学过 ...

  2. 数据结构入门学习之数据结构学些什么?

    在刚开始学习数据结构,我推荐一定要搞懂三个问题,这将对我们学习数据结构的帮助很大,能让我们对数据结构有一个清晰的认识,问题如下 1.学习数据结构是干嘛用的? 2.什么是数据结构? 3.数据结构要学习什 ...

  3. 数据结构入门(一级)

    数据结构和算法的入门:在这里我们先回答大家三个问题1. 为什么要学习数据结构2. 有哪些数据结构3. 学习数据结构的四种境界知道了这三个问题之后呢,再来进行具体内容的一个学习,先看第一个,为什么要学些 ...

  4. 数据结构入门最佳书籍_最佳数据科学书籍

    数据结构入门最佳书籍 Introduction 介绍 I get asked a lot what resources I recommend for people who want to start ...

  5. Java数据结构(1.1):数据结构入门+线性表、算法时间复杂度与空间复杂度、线性表、顺序表、单双链表实现、Java线性表、栈、队列、Java栈与队列。

    数据结构与算法入门 问题1:为什么要学习数据结构          如果说学习语文的最终目的是写小说的话,那么能不能在识字.组词.造句后就直接写小说了,肯定是不行的, 中间还有一个必经的阶段:就是写作 ...

  6. 《LeetCode》数据结构入门板块

    文章目录 <LeetCode题>数据结构入门板块 第1天 数组 217.存在重复元素[简单,哈希表] 53.最大子序和[简单,动态规划,贪心] 第2天 数组 1.两数之和[简单,哈希表] ...

  7. 数据结构入门(8) ——查找

    数据结构入门 --查找 文章目录 数据结构入门 --查找 前言 一.线性表查找 顺序查找 有序表的二分查找 对半(折半)查找 二叉判定树 对半查找总结 一致对半查找 斐波那契查找 插值查找 二.查找树 ...

  8. 数据结构入门篇:约夫瑟斯数据环问题

    关于数据结构,在大学本科并未接触,目前才开始接触学习. 关于这个问题,还记得刚刚毕业那会,找工作面试的时候,有一家公司的笔试大题就是约夫瑟斯数据环,然而当时并未接触这个,所以,悲剧了 其实这个很简单, ...

  9. [入门必看]数据结构4.2:串的模式匹配

    [入门必看]数据结构4.2:串的模式匹配 第四章 串 4.2 串的模式匹配 知识总览 4.2.1_朴素模式匹配算法 4.2.2_1_KMP算法 4.2.2_2_求next数组 4.2.3_KMP算法的 ...

  10. 数据结构入门概述笔记,结合英雄联盟游戏举例,通俗易懂!

    数据结构入门 已同步微信公众号乐享Coding,欢迎关注! 程序=数据结构和算法 不知各位有没有玩过一款名为英雄联盟(LOL)的游戏,或者王者荣耀的MOBA类游戏,因为这是数据结构的第一篇文章入门,只 ...

最新文章

  1. Python学习【第七篇】基本数据类型
  2. 第十二课:小信号分析 (二)
  3. JAVA SE 学习day_10:集合、聊天室练习最终版
  4. matlab面向对象排序,matlab面向对象编程基础
  5. linux内核色彩管理,如何在Linux的色彩管理中获得标准结果
  6. oracle pl/sql 中目录的创建
  7. pc端jquery左右按钮控制带缩略图的图片切换代码_Web开发实用的图片预览插件,简单零依赖——PhotoSwipe...
  8. mssql与oracle不同点,MySql,Mssql,Oracle的优缺点和异同(欢迎补充) *
  9. 汇编语言常见错误(转载)
  10. 测开:从0到1,自动化测试接入Jenkins学习
  11. 【转】Linux设备驱动之I/O端口与I/O内存
  12. 你真的掌握 LVS、Nginx 及 HAProxy 的工作原理吗?
  13. AUTOCAD--实时缩放
  14. 多页面-HASH-页面间传值 Sloth-state
  15. 中职计算机教师发言范文话,中职班主任发言稿范文(精选4篇)
  16. python量化策略—— alpha 三因子策略(1)
  17. 一个10年符号主义学者的深度讨论:如何理性看待ChatGPT?
  18. 小程序不用服务器可以上线吗?
  19. 【翻译】ARM虚拟化软件和架构支持的设计,实现和评估
  20. Excel按背景颜色分类统计各颜色个数的操作

热门文章

  1. 微信小程序—自定义(城市选择)弹窗组件,将弹窗组件的值传给调用页面并显示(图文)
  2. 2022年系统集成企业的物联网平台首选:物联集成平台
  3. (ios 5.1).html,iOS 5.1.1完美越狱教程(使用Absinthe 2.0.1)
  4. 安全开发--3--Python实现ARP缓存投毒
  5. Flex Builder 3.0 开发环境
  6. trackmaker翻译_水工词汇翻译
  7. 做好项目管理,先从明确职责开始
  8. 报错Duplicate entry ‘值‘ for key ‘字段名‘的解决解决方法
  9. Qt移植bsdiff算法计算差分文件
  10. php7 phalcon,GitHub - shyn0121/cphalcon7: Phalcon7 - Web framework for PHP7.x 高性能PHP7框架