《极客时间:数据结构与算法之美》【数据结构与算法】

本篇博客是学习过程中的笔记整理和个人思考。
原文链接:https://time.geekbang.org/column/intro/100017301

  • 开篇词 | 从今天起,跨过“数据结构与算法”这道坎
  • 01 | 为什么要学习数据结构和算法?
  • 02 | 如何抓住重点,系统高效地学习数据结构与算法?
  • 03 | 复杂度分析(上):如何分析、统计算法的执行效率和资源消耗?
    • 为什么需要复杂度分析
    • 大 O 复杂度表示法
    • 时间复杂度分析
      • 只关注循环次数最多的一段代码
      • 加法法则:总复杂度等于量级最大的那段代码的是复杂度
      • 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
    • 几种常见时间复杂度实例分析
      • O(1)
      • O(logn)、O(nlogn)
      • O(m+n)、O(m*n)
    • 空间复杂度分析
    • 内容小结
    • 课后思考
  • 18 | 散列表(上):Word文档中的单词拼写检查功能是如何实现的?
    • 散列思想
    • 散列函数
    • 散列冲突
      • 开放寻址法

开篇词 | 从今天起,跨过“数据结构与算法”这道坎

边读边练,写代码时考虑性能方面的问题,进行时间、空间复杂度分析。

遇到问题,解决之后进行思考、研究透彻。

技术人成长的姿势:关注架构和技术趋势的概念、设计思想、实践为能力。

不管上层衍生出来多少新技术、新产品,都依赖于底层的基础知识,所以基础知识才是核心和本质。

基础知识包括:

  • 数据结构与算法。
  • 计算机组成原理。
  • 操作系统。
  • 计算机网络。
  • 编译原理。
  • 数据库原理。

基础知识决定技术高度和建造技术大楼的速度和质量。

学习的过程需要思考和时间,而不是死记硬背,思考怎么用?为什么需要?如何用?设计思想是什么?应用场景有哪些?

所有知识转化为能力的过程,都是逻辑思维的锻炼和动手能力的实践提升,而绝不是死记硬背,机械的重复记忆。

对于生活中遇到问题的态度和处理:
人生路上,我们会遇到很多的坎。跨过去,你就可以成长,跨不过去就是困难和停滞。而在后面很长的一段时间里,你都需要为这个困难买单。对于我们技术人来说,更是这样。既然数据结构和算法这个坎,我们总归是要跨过去,为什么不是现在呢?

数据结构和算法是一个普通程序员和一个优质高潜质程序员之间永远的区分线。

01 | 为什么要学习数据结构和算法?

面试,数据结构和算法基础知识是对长期潜力的考察。

算法思维将实际问题抽象为数学问题,然后用计算机将数学问题用代码进行表示和处理。

学习任何知识如果不是为了去应用解决实际问题,那便毫无意义。

多刁难自己,多给自己提问,然后去解决,在解决的过程中就可以学到更多新知识。简而言之就是在学习方面不要放过自己,随时挑自己的刺。

即使是直接调用类库接口,也至少应该知道根据自己的业务应该调用哪个类的哪些接口,更深层次来说,你经常调用的接口难道就没有兴趣了解一些实现?这些实现凭什么可以被放在标准库中使用?实现的时候有没有什么缺点?如果让你实现,你是否实现的比标准库好?不断给自己提问,然后去解决,解决的过程就会学到更多知识,自己的知识地图不断扩大,深度越深越能接触到底层最本质的原理,逻辑思维能力和解决问题的能力就会不断提升。

如果自己经常使用的东西,都不知道该如何取用,都不知道实现和原理,那是多么可怕的事情。

写出达到开源水平的框架才是目标。

高手之间的竞争是细节的竞争:
算法够不够优化—时间复杂度,数据存取效率是不是够高—响应时间,内存是不是足够节省—空间复杂度。

做事情需要有难度梯度,需要思考,在解决问题的过程中提升能力。走出舒适区,不断锻炼自己。

即学即用,即用即学。

在实践中遇到问题去思考,然后带着问题去学习,是非常高效的学习方法。

学习数据结构和算法的目的:

  • 建立时间、空间复杂度意识,写出高质量的代码,提升编程能力。
  • 能够设计基础架构。
  • 训练逻辑思维。
  • 积攒人生经验。
  • 长期看来,大脑的思考能力是个人最重要的核心竞争力,算法是为数不多的能够有效训练大脑思考能力的途径之一。
  • 获得工作汇报,实现价值。
  • 完善人生。

掌握了数据结构与算法,看待问题的深度,解决问题的角度就会完全不一样。不只是编程方面,生活中的各个方面,遇到各种问题,会因为你的逻辑思维能力获得锻炼和提升而处理的更好。

02 | 如何抓住重点,系统高效地学习数据结构与算法?

生活中遇到的大多数事情,要么已有解决方案,要么有其他领域可以借鉴。如果遇到一个问题是原创问题,那么就自己动脑子解决它,这种解决的过程带来能力和价值的提升是飞速的,也会给自己带来回报。

思考工作中会遇到的技术和框架,也可以不断去了解当下最火的技术,然后剖析背后的原理本质和设计思想。

编程就是实用派,有没有用,效果如何,动手实践才是提升的本质。

数据结构:一组数据在内存中的存储结构。
算法:操作特定数据结构的步骤。(特定理解为数据结构和算法存在适配关系。)

数据结构和算法是前人的智慧,经过求证和实践检验,可以帮助我们高效地解决很多实际开发中的问题。

选择正确的数据结构会让算法变得简单和高效,有些算法只能在特定的数据结构上操作。

思考实际应用场景?是什么?为什么?怎么实现的?怎么使用?设计思想是什么?

写代码的时候时刻要考虑时间复杂度和空间复杂度。

本质上在工作生产中,到底选取哪种数据结构和算法,是由复杂度分析决定的,我们剖析很多开源代码,剖析STL本质都是为了研究设计思想和实现对于时间复杂度和空间复杂度是如何影响的。

为什么说复杂度分析是数据结构和算法的精髓,就是因为所有的数据结构和算法都需要考虑时间复杂度和空间复杂度,对于我们在实际开发工作中有着绝对的影响,实践过程中就是不断思考时间复杂度和空间复杂度更低的数据结构和算法,不断提高性能和节省空间。

数据结构和算法解决的问题:更快运行,更省内存。

数据结构和算法知识图:
数据结构和算法知识图

10个常用数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie树。
10个常用算法:排序、递归、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法。

从学习的本质来说,任何学习都是不是死记硬背,而是应用将知识转化为能力,学习数据结构和算法更是如此,多辩证思考,多给自己提问:为什么会有?有什么特点?解决了什么问题?有什么应用场景?如何实现的?等,然后不断解决问题,在解决问题的过程中学习更多,锻炼自己的能力。

简单小结就是:边学边练,带着问题学习,即用即学,即学即用。多问、多思考、多交流、多动手实践。完全弄懂,避免一知半解。

学习的过程中,能力是不断迭代式螺旋上升的,遇到问题和不懂的是非常正常的,你要给自己留有容错空间。很多问题会随着你知识和能力不断提升和豁然开朗。

03 | 复杂度分析(上):如何分析、统计算法的执行效率和资源消耗?

数据结构和算法解决的是:如果在计算机内存更快时间、更省空间的解决问题。

从执行时间和占用空间两个维度来评估数据结构和算法的性能。

用时间复杂度和空间复杂度来描述性能,二者统称为复杂度。

复杂度描述的是算法执行时间(或占用内存空间)与数据规模的的增长关系。

复杂度分析不依赖于执行环境,成本低,效率高,易操作,指导性强。

掌握复杂度分析,编写出性能更优的代码。

算法的执行时间与每行代码的执行次数成正比,T(n) = O(f(n)),T(n)表示算法执行总时间,f(n) 表示每行代码的执行总次数,n表示数据规模。

时间复杂度(空间复杂度)描述算法的执行时间(额外占用空间)随数据规模增长变化的趋势。常量阶、低阶、系数对增长趋势不产生决定性影响,分析是可以忽略。

时间复杂度:单段代码看高频率(循环),多段代码取最大(单循环和多重循环取多重循环),嵌套代码求乘积(递归,多重新循环等),多个规模求加法(两个参数控制两个循环次数,取二者时间复杂度相加)。

复杂度级别:
多项式比例增长:O(1),O(logn),O(n),O(nlogn),O(n ^ 2),O(n ^ 3)。
非多项式暴增:O(2^n),O(n!)。

多练习分析时间复杂度。

遇到一个新的思路:数据结构横向解决运算时间快和空间省的问题,纵向解决架构和抽象的问题(数据结构和算法的泛型)。

所有数据结构和算法都会涉及时间复杂度和空间复杂度的问题。

为什么需要复杂度分析

先进行良好的设计,然后根据设计进行分析改进,最后再去执行。

事后统计法存在局限性:

  • 测试结果依赖环境。
  • 测试结果受数据规模影响很大。

举例:计算乘法。测试环境其中影响非常大的就是硬件,对于不同的指令集系统就会对结果有影响,乘法

通过时间复杂度、空间复杂度分析,进行粗略计算算法的执行效率。

很多算法都是适配固定的数据结构和应用场景,没有任何场景都是适用的完美算法。

大 O 复杂度表示法

算法的执行效率:算法代码执行时间越短,效率越高。

 int cal(int n) {int sum = 0;int i = 1;for (; i <= n; ++i) {sum = sum + i;}return sum;}

从CPU的角度看,每一个语句都执行着类似的操作:读数据-运算-写数据。
假设每个语句的执行时间都是一样的为unit_time。

第2行执行 1 次。
第3行执行 1 次。
第4行 i <= n 执行 n + 1次,++i 执行 n 次。
第5行执行了 n 次。

第7行执行 1 次。
这段代码总的执行时间:(3n + 4) * unit_time。

 int cal(int n) {int sum = 0;int i = 1;int j = 1;for (; i <= n; ++i) {j = 1;for (; j <= n; ++j) {sum = sum +  i * j;}}}

第2行执行 1 次。
第3行执行 1 次。
第4行执行 1 次。
第5行 i <= n 执行 n + 1次,++i 执行 n 次。
第6行执行 n 次。
第7行 j <= n 执行 n ^ 2 + 1次,++j 执行 n ^ 2 次。
第8行 n ^ 2 次。
这段代码总的执行时间:(3n ^ 2 + 3n + 5) * unit_time。

所有代码的执行时间 T(n) 与每行代码的执行次数 f(n) 成正比。

总结规律:
大O表示法
T(n):代码执行时间。
n:数据规模。
f(n):每个语句执行总次数。
O:代码执行时间 T(n) 和 f(n) 表达式成正比。

上面两个例子用大 O 时间复杂度表示为:
T(n) = O(3n + 4)
T(n) = O(3n ^ 2 + 3n + 5)

大 O 时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度(asymptotic time complexity),我们最终想要的肯定是随数据规模时间和空间增加速度最慢的复杂度。

公式中的低阶、常量、系数三部分并不左右增长趋势,可以忽略。
上面两个例子用忽略后的大 O 时间复杂度表示为:
T(n) = O(n)
T(n) = O(n ^ 2)

时间复杂度分析

只关注循环次数最多的一段代码

 int cal(int n) {int sum = 0;	//常量int i = 1;	//常量for (; i <= n; ++i) {	//nsum = sum + i;	//n}return sum;	//常量}

T(n) = O(n)。

加法法则:总复杂度等于量级最大的那段代码的是复杂度

int cal(int n) {int sum_1 = 0;	//常量int p = 1;	//常量for (; p < 100; ++p) {	//nsum_1 = sum_1 + p;	//n}int sum_2 = 0;	//常量int q = 1;	//常量for (; q < n; ++q) {	//nsum_2 = sum_2 + q;	//n}int sum_3 = 0;	//常量int i = 1;	//常量int j = 1;	//常量for (; i <= n; ++i) {	//nj = 1; 	//nfor (; j <= n; ++j) {	//n^2sum_3 = sum_3 +  i * j;	//n^2}}return sum_1 + sum_2 + sum_3;	//常量}

T(n) = O(n^2)。

将规律抽象成公式:
T1(n)=O(f(n)),T2(n)=O(g(n));那么 T(n)=T1(n)+T2(n)=max(O(f(n)), O(g(n))) =O(max(f(n), g(n)))

乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

int cal(int n) {int ret = 0; 	//常量int i = 1;	//常量for (; i < n; ++i) {	//nret = ret + f(i);	//n^2} } int f(int n) {int sum = 0;	//常量int i = 1;	//常量for (; i < n; ++i) {	//nsum = sum + i;	//n} return sum;//常量}

T(n) = T1(n) * T2(n) = O(n*n) = O(n2)。

几种常见时间复杂度实例分析

常见复杂度分析实例分析
多项式复杂度量级::O(1)、O(logn)、O(n)、O(nlogn)、O(n2 )

非多项式复杂度量级( NP(Non-Deterministic Polynomial,非确定多项式)问题。):O(2n) 和 O(n!)。
非多项式复杂度量级是非常低效的。

O(1)

 int i = 8;int j = 6;int sum = i + j;

只要代码的执行时间不随 n 的增大而增长,时间复杂度就是 O(1)。
一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是Ο(1)。

O(logn)、O(nlogn)

 i=1;while (i <= n)  {i = i * 2;}

每次取值

求取了多少次 x
2^x = n
x = log2n

时间复杂度为:O(log2n)。

 i=1;while (i <= n)  {i = i * 3;}

log3n 等于 log32 * log2n

O(log3n) = O(C * log2n)

C=log32 是一个常量,可以忽略: O(Cf(n)) = O(f(n))

O(log2n) 等于 O(log3n)

对数阶时间复杂度里面,忽略底,同意表示为 O(logn) 。

O(m+n)、O(m*n)

int cal(int m, int n) {int sum_1 = 0;int i = 1;for (; i < m; ++i) {sum_1 = sum_1 + i;}int sum_2 = 0;int j = 1;for (; j < n; ++j) {sum_2 = sum_2 + j;}return sum_1 + sum_2;
}

无法事先评估 m 和 n 那个量级更大。时间复杂度:O(m +n)。

通用规则:
T1(m) + T2(n) = O(f(m) + g(n))。

乘法规则继续有效:
T1(m)*T2(n) = O(f(m) * f(n))。

空间复杂度分析

void print(int n) {int i = 0;int[] a = new int[n];for (i; i <n; ++i) {a[i] = i * i;}for (i = n-1; i >= 0; --i) {print out a[i]}
}

第2行,申请1个空间存储变量,常数阶。
第三行,申请大小为 n 的数组,空间复杂度为 O(n)。

整段代码空间复杂度为:O(n)。

内容小结

常见复杂度从底到高::O(1)、O(logn)、O(n)、O(nlogn)、O(n2 )

常见复杂度
复杂度分析并不难,关键在于多练。

课后思考

有人说,我们项目之前都会进行性能测试,再做代码的时间复杂度、空间复杂度分析,是不是多此一举呢?而且,每段代码都分析一下时间复杂度、空间复杂度,是不是很浪费时间呢?你怎么看待这个问题呢?

我不认为是多此一举,渐进时间,空间复杂度分析为我们提供了一个很好的理论分析的方向,并且它是宿主平台无关的,能够让我们对我们的程序或算法有一个大致的认识,让我们知道,比如在最坏的情况下程序的执行效率如何,同时也为我们交流提供了一个不错的桥梁,我们可以说,算法1的时间复杂度是O(n),算法2的时间复杂度是O(logN),这样我们立刻就对不同的算法有了一个“效率”上的感性认识。

当然,渐进式时间,空间复杂度分析只是一个理论模型,只能提供给粗略的估计分析,我们不能直接断定就觉得O(logN)的算法一定优于O(n), 针对不同的宿主环境,不同的数据集,不同的数据量的大小,在实际应用上面可能真正的性能会不同,个人觉得,针对不同的实际情况,进而进行一定的性能基准测试是很有必要的,比如在统一一批手机上(同样的硬件,系统等等)进行横向基准测试,进而选择适合特定应用场景下的最有算法。

综上所述,渐进式时间,空间复杂度分析与性能基准测试并不冲突,而是相辅相成的,但是一个低阶的时间复杂度程序有极大的可能性会优于一个高阶的时间复杂度程序,所以在实际编程中,时刻关心理论时间,空间度模型是有助于产出效率高的程序的,同时,因为渐进式时间,空间复杂度分析只是提供一个粗略的分析模型,因此也不会浪费太多时间,重点在于在编程时,要具有这种复杂度分析的思维。

懂得了时间复杂度、空间复杂度分析之后,在写代码的时候,就会去尽可能寻找最优的算法。而性能测试,则是代码写完之后,才能进行的。只能是事后的。

上述回答来源于留言区的置顶回答,写的真好,把我想说又说不好的话都说了出来。

18 | 散列表(上):Word文档中的单词拼写检查功能是如何实现的?

散列思想

散列表,HashTable,哈希表,Hash表,都是同一个表达。

散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展。

将 键 key(或者关键字),通过散列函数(或Hash函数、哈希函数)映射计算得到散列值(或Hash值、哈希值),将散列值作为数组下标。

TUTU

总结规律:散列表用的就是数组支持按照下标随机访问的时候,时间复杂度是 O(1) 的特性。我们通过散列函数把元素的键值映射为下标,然后将数据存储在数组中对应下标的位置。当我们按照键值查询元素时,我们用同样的散列函数,将键值转化数组下标,从对应的数组下标的位置取数据。

散列函数

定义成 hash(key),其中 key 表示元素的键值,hash(key) 的值表示经过散列函数计算得到的散列值。

散列函数设计的基本要求:

  1. 散列函数计算得到的散列值是一个非负整数;(数组下标从0开始)
  2. 如果 key1 = key2,那 hash(key1) == hash(key2);
  3. 如果 key1 ≠ key2,那 hash(key1) ≠ hash(key2)。

第三个条件,在真实的情况下,要想找到一个不同的 key 对应的散列值都不一样的散列函数,几乎是不可能的。
像业界著名的MD5、SHA、CRC等哈希算法,也无法完全避免这种散列冲突。
因为数组的存储空间有限,也会加大散列冲突的概率。

MD5哈希算法:

SHA哈希算法:

CRC哈希算法:

散列冲突

开放寻址法

开放寻址法的核心思想是,如果出现了散列冲突,我们就重新探测一个空闲位置,将其插入。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IDEA中的MySQL数据库所需驱动包的下载和导入方法

文章目录 下载驱动导入方法 下载驱动 MySQL数据库驱动文件下载方法&#xff1a; 最新版的MySQL版本的驱动获取方法&#xff0c;这个超链接是下载介绍的博客 除最新版以外的MySQL版本的驱动获取方法&#xff0c;选择Platform Independent&#xff0c;选择第二个zip压缩包虾藻…

【鲁棒电力系统状态估计】基于投影统计的电力系统状态估计的鲁棒GM估计器(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

04_瑞萨GUI(LVGL)移植实战教程之驱动LCD屏(SPI)

本系列教程配套出有视频教程&#xff0c;观看地址&#xff1a;https://www.bilibili.com/video/BV1gV4y1e7Sg 4. 驱动LCD屏(SPI) 本次实验我们在上一次实验的基础上驱动 LCD屏(SPI)。 上次实验我们已经能驱动触摸屏(I2C)并打印触摸点坐标&#xff0c;这次实验我们的目标是点…

CRC原理介绍及STM32 CRC外设的使用

1. CRC简介 循环冗余校验&#xff08;英语&#xff1a;Cyclic redundancy check&#xff0c;简称CRC&#xff09;&#xff0c;由 W. Wesley Peterson 于 1961 年首次提出的一种纠错码理论。 CRC是一种数据纠错方法&#xff0c;主要应用于数据通信或者数据存储的场合&#xff…

《Go语言在微服务中的崛起:为什么Go是下一个后端之星?》

&#x1f337;&#x1f341; 博主猫头虎&#x1f405;&#x1f43e; 带您进入 Golang 语言的新世界✨✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f…

【云原生系列】Docker学习

目录 一、Docker常用命令 1 基础命令 2 镜像命令 2.1 docker images 查看本地主机的所有镜像 2.2 docker search 搜索镜像 2.3 docker pull 镜像名[:tag] 下载镜像 2.4 docker rmi 删除镜像 2.5 docker build 构建镜像 3 容器命令 3.1 如拉取一个centos镜像 3.2 运行…

leetcode897. 递增顺序搜索树(java)

递增顺序搜索树 题目描述中序遍历代码演示 递归专题 题目描述 难度 - 简单 LC - 897. 递增顺序搜索树 给你一棵二叉搜索树的 root &#xff0c;请你 按中序遍历 将其重新排列为一棵递增顺序搜索树&#xff0c;使树中最左边的节点成为树的根节点&#xff0c;并且每个节点没有左子…

【Linux】进程间通信(匿名管道、命名管道、共享内存等,包含代码示例)

进程间通信 前言正式开始理解进程间通信一些标准管道原理管道演示匿名管道代码演示原理进程池管道大小 命名管道演示代码分配消息例子 systemV共享内存共享内存流程获取key值shm的创建shm的删除关联去关联完整流程演示开始通信 systemV 消息队列基于对共享内存的理解几个概念 前…

Kafka3.0.0版本——消费者(手动提交offset)

目录 一、消费者&#xff08;手动提交 offset&#xff09;的概述1.1、手动提交offset的两种方式1.2、手动提交offset两种方式的区别1.3、手动提交offset的图解 二、消费者&#xff08;手动提交 offset&#xff09;的代码示例2.1、手动提交 offset&#xff08;采用同步提交的方式…

解决ul元素不能跟div同一行显示的办法

现象如下&#xff1a; html结构如下&#xff1a; 可以看到div和ul是同级元素。 为什么这里ul换行了呢&#xff01; 这里要敲黑板了&#xff01; 因为ul是块级元素&#xff01;也就是独占一行&#xff0c;跟div一样。 如果需要ul跟div在同一行显示&#xff0c;则要求ul前面相…

基于改进二进制粒子群算法的含需求响应机组组合问题研究(matlab代码)

目录 1 主要内容 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序复现《A Modified Binary PSO to solve the Thermal Unit Commitment Problem》第五章内容&#xff0c;主要做的是一个考虑需求响应的机组组合问题&#xff0c;首先构建了机组组合问题的基本模型&#x…

一文了解Android App Bundle 格式文件

1. Android App Bundle 是什么&#xff1f; 从 2021 年 8 月起&#xff0c;新应用需要使用 Android App Bundle 才能在 Google Play 中发布。 Android App Bundle是一种发布格式&#xff0c;打包出来的格式为aab&#xff0c;而之前我们打包出来的格式为apk。编写完代码之后&a…

vue3:5、组合式API-reactive和ref函数

<script setup> /* reactive接收一个对象类型的数据&#xff0c;返回一个响应式的对象 *//*** ref:接收简单类型或复杂类型&#xff0c;返回一个响应式对象* 本质&#xff1a;是在原有传入数据的基础上&#xff0c;外层报了一层对象&#xff0c;包成了复杂类型* 底层&…

Python小知识 - 如何使用Python进行机器学习

如何使用Python进行机器学习 Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。 机器学习是人工智能的一个分支&#xff0c;是让计算机自动“学习”。学习的过程是从经验E中获得知识K。经验E可以是一个数据集&#xff0c;比如一个图像数据集。知识K可以是计算机…

07_瑞萨GUI(LVGL)移植实战教程之LVGL对接EC11旋转编码器驱动

本系列教程配套出有视频教程&#xff0c;观看地址&#xff1a;https://www.bilibili.com/video/BV1gV4y1e7Sg 7. LVGL对接EC11旋转编码器驱动 本次实验我们向LVGL库中对接EC11旋转编码器驱动&#xff0c;让我们能通过EC11旋转编码器操作UI。 7.1 复制工程 上次实验得出的工…

景区AR虚拟三维场景沉浸式体验成为新兴的营销手段

科技的迅速崛起正在改变我们的世界&#xff0c;旅游业也在这股浪潮中掀起了一场全新的变革。增强现实(AR)技术正成为旅行中的一股强大力量&#xff0c;通过增添趣味和交互性&#xff0c;为旅程注入了前所未有的活力。本文将带您深入了解AR如何为旅游带来全新的体验&#xff0c;…

Docker 实现 MySQL 一主一从配置

1、新建主服务器容器实例&#xff0c;端口&#xff1a; 3307 docker run \ -p 3307:3306 \ --name mysql-master \ -v /var/docker/mysql-master/log:/var/log/mysql \ -v /var/docker/mysql-master/data:/var/lib/mysql \ -v /var/docker/mysql-master/conf:/etc/mysql \ --p…

【EI会议征稿】第三届机械自动化与电子信息工程国际学术会议(MAEIE 2023)

第三届机械自动化与电子信息工程国际学术会议&#xff08;MAEIE 2023&#xff09; 第三届机械自动化与电子信息工程国际学术会议&#xff08;MAEIE 2023&#xff09;将于2023年12月15-17日在江苏南京举行。本会议通过与业内众多平台、社会各团体协力&#xff0c;聚集机械自动…

【微信读书】数据内容接口逆向调试01

需求爬取微信读书的某一本书的整本书的内容 增强需求&#xff0c;大批量爬取一批书籍内容 众所周知微信读书是一个很好用的app&#xff0c;他上面书籍的格式很好&#xff0c;质量很高。 本人充值了会员但是看完做完笔记每次还得去翻很不方便&#xff0c;于是想把书籍内容弄下…

Visual Studio 线性表的链式存储节点输出引发异常:读取访问权限冲突

问题&#xff1a; 写了一个线性表的链式存储想要输出&#xff0c;能够输出&#xff0c;但是会报错&#xff1a;读取访问权限冲突 分析&#xff1a; 当我们输出到最后倒数第二个节点时&#xff0c;p指向倒数第二个节点并输出&#xff1b; 下一轮循环&#xff1a;p指向倒数第二…