编程的艺术
编程的艺术不仅仅是编写代码。它涉及我们的思维过程、解决问题的方法以及我们对世界的影响。编程是一种创造性的语言,它将想法变为现实,并允许我们通过技术表达自己。它挑战我们创新思考,寻找非常规的解决方案,并扩大我们对世界和我们自己的理解。该视频探讨了基本的编程概念,从基本语法和数据结构到高级算法和编程范例。让我们开始。
在编辑代码方面,主要有两种类型的工具:文本编辑器和 IDE。虽然文本编辑器专注于编辑纯文本,但 IDE 提供了其他功能。然而,对于大多数用途来说,两者之间的区别并不重要,并且这些术语可以互换使用。文本编辑器和 IDE 的热门选项包括 Vim、Atom、Sublime Text、Eclipse、IntelliJ、PyCharm 和 Visual Studio Code。特别是 Visual Studio Code 具有高度可定制性并得到广泛推荐。
要运行代码,我们需要将其编译成计算机可以理解的机器代码。这需要安装语言编译器或运行时。不同的语言有自己的编译器或运行时,例如GCC、Java SDK、Python解释器、Node.js运行时和.NET SDK。没有必要了解这些工具的细节;您需要知道的只是安装一种语言来运行您的代码。
运行代码涉及使用终端,终端提供对命令行界面的访问。常用的终端包括 Powershell 和 Bash。终端允许我们执行创建目录、列出文件和运行程序等命令。包管理器(例如 Node.js 的 npm 和 Python 的 pip)可用于通过命令行从存储库安装软件。 Git 是一种版本控制系统,对于管理代码更改和与他人协作至关重要。
要开始编码,您需要合适的文本编辑器或 IDE、语言编译器以及终端命令的基本知识。 Visual Studio Code 是文本编辑器或 IDE 的推荐选择。安装编程语言并熟悉终端命令将使您能够编写和运行代码。学习编程语言涉及理解它们的语法、环境和约定。不同的语言具有不同的复杂程度,但它们在结构和概念上都有相似之处。
可以使用每种语言特定的函数或方法来完成不同编程语言的打印输出。例如,Python有内置的打印功能,JavaScript有console.log方法,Java和C++有自己的打印到标准输出的语法。
变量用于存储不同数据类型的值。变量是用值声明、定义和初始化的。编程语言可以是静态类型的或动态类型的,并且它们具有不同的变量语法。静态类型需要显式声明变量类型,而动态类型则不需要。变量具有作用域,它决定了可以在程序中的何处访问和使用变量。范围可以是全局的或局部的,它可以更好地组织和预防错误。
数据类型表示不同类型的数据,例如字符串、布尔值、整数、浮点数、字符和数组。数据结构提供了一种组织和操作数据的方法。流行的数据结构包括数组、栈、堆、树、链表、哈希表、哈希图和图。数组和映射是两种常用的数据结构,具有多种应用。
总之,编程是一门艺术,包括思考、解决问题和通过代码塑造世界。它涉及使用文本编辑器或 IDE、通过编译器或运行时运行代码以及理解终端命令和版本控制。学习编程语言需要掌握语法、变量、数据类型和数据结构。该视频对这些概念进行了高级概述,以帮助您开始编程之旅。
- 2023.05.11
- www.youtube.com
编写软件的艺术
计算机就像乐器一样,是精心设计的机器,旨在根据收到的指令执行特定任务。这些用代码编写的指令是指导其操作的软件。正如乐谱是作曲家使用的代码一样,计算机程序员也使用软件代码来创建程序。
编程可以成为快乐和满足的源泉,类似于诗人或音乐家所经历的感受。早期的计算机对于那些喜欢解决问题和解决复杂问题的人来说是令人着迷的,并且赋予他们力量。它们的运行速度惊人,能够解决各种各样的问题,只要使用计算机的本机命令来表达即可。但是,计算机本质上是愚蠢的,需要精确的指令才能理解要做什么。早期的程序员必须使用代表二进制命令的数字来编写机器语言。这个过程既乏味又容易出错,从而导致了更人性化的编程语言的开发。
Fortran 和 COBOL 等高级语言的引入使编程变得更加容易。程序员可以使用熟悉的科学公式或对他们有意义的逻辑语句来表达他们的指令。然后使用编译器将这些指令翻译成计算机的二进制语言。这一突破开启了软件革命,因为程序员不再需要学习每台计算机的特定机器语言。
多年来,已经开发了数百种编程语言来满足不同的需求。这些语言与机器语言之间的差距已经扩大,使程序员能够专注于他们想要实现的目标,而不是底层细节。随着计算变得更加个人化,编程语言变得更加多样化和用户友好。人们现在经常通过告诉计算机做什么来与计算机进行交流,例如计算平均值或组织数据。编程已成为一种赋予个人权力的工具,使他们能够根据自己的需求定制和调整计算机系统。
编写软件不仅涉及编码,还涉及定义数据的表示和组织方式。根据需要,数据可以组织成字符串、列表、表格、树等。语言和数据结构的选择对于有效解决编程问题至关重要。程序员创建称为算法的逐步程序来解决问题。这些算法指定了实现预期结果所需的操作。然而,为给定问题找到最有效的算法可能是一项复杂的任务。它需要仔细的思考、专注,有时还需要专业领域的广泛知识。
软件开发是一项具有挑战性和创造性的工作,需要同时牢记多个方面。程序员不断适应技术的进步,突破计算机所能实现的界限。他们力求代码的优雅和连贯,创造出既实用又美观的软件。通过他们的努力,软件程序员扩展了我们的能力,使我们能够利用大量信息并以曾经被认为神奇的方式与世界互动。编程是让计算机工作并塑造我们当今生活的高科技世界的驱动力。
- 2014.11.17
- www.youtube.com
C++ 初学者教程 - 完整课程
00:00:00 - 01:00:00 该视频是针对想要学习如何使用 C++ 进行编码的初学者的教程。它涵盖了使用字符串、数字和变量的基础知识。它还介绍了从其他文件导入代码的概念。
01:00:00 - 02:00:00 此 C++ 初学者教程介绍了如何构建四函数计算器。本教程介绍了如何输入数据、检查运算符相等性以及如何根据该条件执行代码。
02:00:00 - 03:00:00 该视频提供了 C++ 编程的基本介绍,重点是使用 for 循环来计算特定结果。演示的函数计算一个数字的特定幂的结果。
03:00:00 - 04:00:00 在这个面向初学者的 C++ 教程中,讲师演示了如何使用继承来扩展类层次结构中的功能。继承允许一个类具有与另一个类相同的功能,同时使用附加功能扩展该功能。讲师还演示了如何重写继承的函数以更改类的行为。
第1部分
- 00:00:00 该视频教程教初学者如何编写基本的 C++ 代码。第一步是安装文本编辑器和 C++ 编译器,它们都包含在 codeblocks 包中。然后教程展示了如何在代码块中设置一个简单的项目。
- 00:05:00 本教程简要介绍了 C++ 编程语言以及编写和运行 C++ 程序所需的工具。本教程的第一部分展示了如何在 Mac 上安装必要的工具,第二部分介绍了如何在代码块中创建新的 C++ 项目。
- 00:10:00 在本视频教程中,演示者逐步介绍了编写 C++ 程序的基础知识。他介绍了 C++ 项目和文件的需求,解释了函数,并展示了如何构建和运行程序。
- 00:15:00 本教程介绍如何用 C++ 编写基本代码,以及如何使用 print 语句将信息输出到控制台。
- 00:20:00 在此视频中,演示者通过提供打印故事的程序示例,展示了变量在编程中的作用。然后演示者演示如何创建一个名为“角色名称”的变量并为其赋值,该变量存储角色的名称。接下来,演示者演示如何创建一个名为“age”的变量并为其赋值,该变量存储角色的年龄。最后,演示者演示了如何使用一个变量来存储多条数据。
- 00:25:00 在此视频中,演示者介绍了变量的概念,并展示了如何使用它们在程序中存储数据。他们演示了如何使用 print 语句访问和操作存储在变量中的数据。最后,他们展示了如何在打印语句中包含变量,以便将数据打印在单独的字符串中。
- 00:30:00 该视频介绍了 C++ 中变量和数据类型的概念。变量是存储数据的容器,您可以使用它来存储任何类型的信息。字符串是一种常见的变量类型,它们是字符序列。您还可以使用整数来存储整数,或使用负整数来存储负数。您还可以将十进制数存储在整数中。
- 00:35:00 本教程涵盖了 C++ 编程的基础知识,从简单的文本和数字开始,然后转向更复杂的数据类型,例如字符串和布尔值。
- 00:40:00 该视频介绍了如何使用 C++ 字符串函数长度和字符串索引来打印字符串并确定字符串中特定字符的位置,以及如何修改字符串中的特定字符。
- 00:45:00 该视频介绍了在 C++ 中使用字符串的基础知识,包括如何将参数传递给函数,以及如何使用不同的数学函数来操作字符串。
- 00:50:00 在本 C++ 教程中,涵盖了数字、加法、减法、乘法和除法的基础知识。还引入了模运算符,它对于两个数字相除并计算余数非常有用。最后演示了在变量中存储数字。
- 00:55:00 这个针对初学者的 C++ 教程解释了如何使用数学函数来解决问题。函数包括平方根、pow 和 round。还解释了从其他文件导入代码。
第2部分
- 01:00:00 在这个面向初学者的 C++ 教程中,系统会提示用户输入他们的年龄和姓名。然后,程序将信息存储在名为“年龄”的变量中,并打印用户的姓名和年龄。
- 01:05:00 该视频教程展示了如何用 C++ 创建基本计算器,以及如何构建 Mad Libs 游戏。
- 01:10:00 该视频介绍了如何在 C++ 中创建和使用数组。数组与变量类似,但可以保存多个值。
- 01:15:00 本视频教程介绍了 C++ 中数组的基础知识。数组是一个可以存储多条数据的容器,您可以通过索引或通过为数组的“size”属性赋值来访问各个元素。
- 01:20:00 在本教程中,作者演示了如何在 C++ 中创建函数。函数是执行特定任务并且可以在整个程序中重用的代码块。函数的返回类型可以是 void 或整数。作者还演示了如何调用函数。
- 01:25:00 在此视频中,作者解释了函数的工作原理以及如何重用它们。他还展示了如何创建函数签名以及如何使用其签名调用函数。最后,他讨论了 C++ 中的返回,即函数向调用者返回信息的情况。
- 01:30:00 视频讨论了如何在 C++ 中创建函数以及如何使用 return 关键字来指示函数执行完毕。该视频还演示了如何使用cube函数返回数字的立方结果。
- 01:35:00 在本教程中,作者向初学者介绍了 C++ 中的 if 语句。 if 语句是一种允许程序响应不同情况的编程结构。作者演示了如何使用 if 语句来检查条件,以及如何创建更复杂的 if 语句。
- 01:40:00 本视频教程介绍了如何在 C++ 中使用 and 和 or 运算符来检查两个条件。如果任一条件为假,则整个 if 块将为假并且代码将不会被执行。
- 01:45:00 在本教程中,作者向初学者教授 if 语句,解释如何使用比较来创建 true 或 false 值。该函数将接受两个数字作为输入,并返回最大的数字。
- 01:50:00 该视频介绍了 C++ 中比较的工作原理,以及如何使用大于、小于和等于来检查两个数字是否等于或大于或等于。
- 01:55:00 这个面向初学者的 C++ 教程教授如何构建一个四函数计算器,包括如何输入数据、检查运算符相等性以及如何根据该条件执行代码。
第三部分
- 02:00:00 在本视频教程中,演示了将整数转换为星期几的函数。创建该函数,并使用 if 语句来确定给定的天数是否为 1 或更大。如果是 1,则函数返回“Sunday”;如果不是,该函数返回“Monday”。
- 02:05:00 该视频介绍了如何使用 switch 语句来提高 if 语句中的代码效率。该视频接着解释了如何为一周中的每一天创建 switch 语句,并通过打印作为输入传入的数字的星期几来演示该功能。
- 02:10:00 该视频概述了视频“C++ 初学者教程 - 完整课程”。该视频演示了如何在满足条件时使用 while 循环来迭代代码块。
- 02:15:00 这个面向初学者的 C++ 教程涵盖了循环的基础知识,包括如何创建 while 循环和 do while 循环。该视频还讨论了无限循环以及如何避免它们。最后演示了一个for循环。
- 02:20:00 本教程演示如何使用 while 循环和 do while 循环创建猜谜游戏。该游戏最初是不公平的,因为用户可以进行无限的猜测,但本教程展示了如何通过施加猜测限制来使游戏更加公平。
- 02:25:00 在此视频中,作者解释了 for 循环的工作原理以及如何在 C++ 中使用它们。他还展示了如何使用 for 循环来解决问题的示例。
- 02:30:00 在此视频中,作者解释了 while 循环,这是一种循环构造,其中变量每次执行时都会发生变化。 for 循环是类似的构造,但它包括变量声明、初始化和循环条件。
- 02:35:00 本视频教程演示了如何使用 for 循环来迭代数组的内容,以及如何构建一个将数字取特定幂的函数。
- 02:40:00 本视频教程提供了 C++ 编程的基本介绍,重点是使用 for 循环来计算特定结果。演示的函数计算一个数字的特定幂的结果。
- 02:45:00 在本教程中,作者展示了如何创建和使用二维数组,并讨论了如何访问其中的元素。
- 02:50:00 本视频教程介绍了 C++ 语言,并演示了如何使用 for 和 int 迭代器循环访问数据数组。嵌套的 for 循环允许轻松迭代数组中的数据。
- 02:55:00 该视频解释了指针是什么、它们如何有用以及如何在 C++ 中创建它们。
第 4 部分
- 03:00:00 该视频向初学者介绍了 C++ 编程,并提供了如何使用变量和常量来存储信息的示例。该视频还演示了如何访问内存地址以检索存储在其中的信息。
- 03:05:00 该视频概述了视频“C++ 初学者教程 - 完整课程”。在视频中,演示者演示了如何使用指针访问变量的内存地址。指针只是一个内存地址,只是一种数据类型,您可以使用它来存储指向不同变量的指针。
- 03:10:00 本教程解释了如何在编程中使用指针,并演示如何取消引用它们以访问存储在特定内存地址的值。此外,本教程还讨论了 C++ 中的类和对象,并演示了如何创建和使用类。
- 03:15:00 在这个针对初学者的 C++ 教程视频中,作者创建了一个类来代表书籍。该类有两个属性,标题和作者。然后,作者创建一个书籍对象并设置标题和作者。
- 03:20:00 该视频教初学者如何在 C++ 中创建和使用对象。对象是类的实际实例,类是数据类型的模板。可以打印对象并更改其值。
- 03:25:00 该视频解释了构造函数在 C++ 中的工作原理以及如何使用它们来初始化具有默认值的对象。
- 03:30:00 本视频教程介绍了如何创建接受标题、作者和页面作为输入值的 C++ 构造函数。初始化后,构造函数可用于创建新对象,而无需每次都传入值。
- 03:35:00 该视频解释了如何使用 C++ 中的函数来确定学生是否获得荣誉。函数是模板,每个对象都可以使用这些模板根据对象自己的 GPA 返回 true 或 false。
- 03:40:00 该视频将教初学者如何在 C++ 类中使用 getter 和 setter。 Getter 和 Setter 允许您控制对类中的属性和元素的访问。此示例演示如何使用 getter 和 setter 强制对电影进行有效评级。
- 03:45:00 在这个面向初学者的 C++ 教程中,作者演示了如何使用 getter 和 setter 来限制可分配给电影对象的评级。如果传入的评级不是有效评级之一,则会引发错误或不设置评级。
- 03:50:00 在此视频中,作者解释了如何使用 C++ 设置视频的评级。首先,他们解释了 C++ 中评级的表示方式,评级等于正值(如 13)或负值(如 -3)。接下来,他们演示了如何使用名为 set rating 的函数设置视频的评级。该函数采用一个参数,该参数是表示评级的字符串。如果输入的评级无效,该函数将返回一个表示未评级的字符串。最后,作者演示了如何使用名为 get rating 的函数打印出视频的评级。该函数不带任何参数,仅返回视频的评级。
- 03:55:00 在这个面向初学者的 C++ 教程中,讲师演示了如何继承函数以及如何在类层次结构中重写它们。这允许一个类具有与另一个类相同的功能,同时通过附加特性扩展该功能。
- 2018.08.24
- www.youtube.com
编程和计算机科学概论 - 完整课程
该视频是针对那些几乎没有编码背景的人的编程和计算机科学初学者指南。它涵盖了适用于任何编程语言的基本概念和技术。该视频解释了在集成开发环境 (IDE) 中编写代码的基础知识,并强调了编程语法的重要性。
视频涵盖的主题包括:
- 编程和计算机科学简介,包括语法和编程规则。
- 使用控制台从程序输出文本。
- 编程中的基本数学运算和模运算符。
- 将字符串打印到控制台。
- 了解变量、数据类型和命名约定。
- 如何在程序中定义、引用和操作变量。
- 探索用于条件执行的 if 语句、elsif 语句和 else 语句。
- 引入数组作为存储相关变量的方式。
- 循环基础知识,包括 for 循环、while 循环和 do-while 循环。
- 了解不同类型的编程错误:语法错误、运行时错误和逻辑错误。
- 调试技术,例如使用打印语句、断点和注释。
- 避免编程错误的策略。
- 使用函数来组织代码并减少重复。
- 从库中导入函数以及函数的命名约定。
- 不同类型的功能及其用途。
- 介绍字典作为灵活的数据存储选项。
- 搜索算法概述,包括线性搜索和二分搜索。
- 递归编程及其用例,包括基本案例概念。
- 计算机科学的软技能,例如解决问题和规划。
- 使用伪代码作为编写代码的规划工具。
- 规划和编写代码的不同方法,包括流程图和时间顺序规划。
- 编程语言和可用学习资源的概述。
该视频全面介绍了编程和计算机科学,为观众提供了开始编码之旅所需的基础。它还建议了其他资源和网站来进一步探讨该主题。
- 00:00:00 该视频涵盖了视频的要点,适合那些对计算机科学和编程感兴趣但不知道从哪里开始并且几乎没有编码背景信息的人。该视频涵盖了计算机编程的基础知识,可应用于您可能想学习的任何和所有编程语言。
- 00:05:00 该视频讨论了编程基础知识、如何在集成开发环境 (IDE) 中编写代码以及编程语法的重要性。
- 00:10:00 该视频介绍了编程和计算机科学,并涵盖了语法和编程规则的基础知识。控制台的主要用途是从程序中输出文本。
- 00:15:00 该视频涵盖了基础数学,包括算术、加法、减法、乘法和除法,以及模数(许多编程语言中的基本运算符)。它还包括将字符串打印到控制台。
- 00:20:00 该视频介绍了编程和计算机科学概念,包括变量、类型和名称。原始变量包括整数、布尔值、浮点数和双精度数。字符串变量存储字符串。 Char 变量保存一个字符。变量对于以易于引用的格式存储信息至关重要。
- 00:25:00 该视频讨论了当我们定义或创建变量时会发生什么、如何引用它们以及如何在我们的程序中操纵它们。需要注意的要点是,变量只是内存中存储特定值的空间,我们可以更新数字,并且它们的位置在整个代码中保持不变。
- 00:30:00 变量是编程时可以存储信息的地方。变量的命名约定对于可读性很重要。如果 if 语句中的条件为 true,则将运行大括号内的代码。还有两个附加语句 elsif 和 eltons,其工作方式与 if 语句类似。如果 elsif 中的条件为 true,则将运行 elsif 后面的代码。否则,elsif后面的代码
将被跳过。如果 elsif 中的条件不成立,则将跳过 elsif 后面的代码并运行 if 语句后面的代码。 - 00:35:00 数组是彼此相关的变量的列表。当程序员想要存储大量包含彼此相关信息的变量时,它们非常有用。
- 00:40:00 编程和计算机科学简介课程涵盖数组、索引、大小以及数组内的数组。循环也被覆盖。
- 00:45:00 该视频介绍了不同类型的循环:for、while 和 do while 循环。它解释了如何设置循环条件以及如何避免无限循环。
- 00:50:00 该视频涵盖了编程过程中可能发生的三种类型的错误:语法错误、运行时错误和逻辑错误。语法错误是最容易修复的,因为它们通常可以在几秒钟内修复。运行时错误是由代码中看似逻辑合理但计算机实际上无法在合理时间内完成任务的语句引起的。逻辑错误是最令人恼火且难以调试的,因为它们通常会导致程序无法按预期运行。要调试代码,您应该增量测试它并查找语法和运行时错误。
- 00:55:00 如果您在代码中遇到错误,您可以使用打印语句和控制台来确定代码出错的位置,使用断点来追踪错误原因,并使用注释来标记出来适合您而不是计算机的代码。最后,讨论了避免错误的策略。
- 01:00:00 在此视频中,讲师介绍了编程和计算机科学的基础知识,包括错误和函数。他接着解释了参数在函数中的工作原理以及如何使用函数来减少代码中的重复。
- 01:05:00 该视频介绍了编程和计算机科学,讨论了四种不同类型的函数、它们的用途以及如何在代码中使用它们。函数有助于组织代码、节省时间以及对代码进行大量更改,而无需遍历整个程序。
- 01:10:00 在本视频中,介绍了编程和计算机科学的基础知识。解释了从库导入函数,并讨论了命名函数的规则。还介绍了根据参数类型和数量创建函数的规则。
- 01:15:00 在此视频中,讲师解释了编程和计算机科学的基础知识,包括函数、范围和参数传递。他还介绍了如何创建不返回任何值的函数。
- 01:20:00 在此视频中,演示者回顾了数组、函数和字典。数组就像存储在一起的值列表,函数根据所采用的路径返回一个变量。需要注意的一个小细节是,如果您已经定义了返回另一种类型的函数,则无法返回一种类型的变量。当列表的大小超过 10 个元素时,数组列表会自行增长,而字典则存储多个值。
- 01:25:00 计算机以不同的方式存储数据,这可能很难理解。字典是一种数据存储类型,它比传统数组更流畅、更容易组织。搜索算法用于快速查找值列表中的特定数据。
- 01:30:00 该视频介绍了搜索算法的概念及其效率。线性搜索对于未排序列表来说是一种很好的基本算法,但在最坏的情况下效率很低。二分搜索是排序列表的一种有效搜索算法,利用了列表已排序的事实。
- 01:35:00 在查找排序列表中的项目时,二分搜索算法比线性搜索更快、更高效。递归函数是递归编程语句的示例。递归语句的基本情况是所有递归语句必须满足的确定值。如果n不小于或等于1,则递归语句将返回n的和,然后将递归求和方法的返回值减1。
- 01:40:00 该视频介绍了编程和计算机科学,并解释了为什么递归是一种有用的技术。计算机科学所需的软技能包括问题解决和规划。伪代码是一种简化的编程形式,可以帮助完成此规划。
- 01:45:00 伪代码是一种规划计算机代码的可视化方式,类似于构建论文大纲。流程图和按时间顺序写出您希望程序执行的操作是两种常见的方法。
- 01:50:00 该视频介绍了编程和计算机科学概念,包括规划和编写代码的不同方法以及伪代码的重要性。它还涵盖了不同的编程语言及其用途。
- 01:55:00 在本系列中,作者介绍了编程基础知识,包括语法和规则,并教授如何学习特定语言。他还提供网站和资源来帮助您入门。
- 2020.04.21
- www.youtube.com
C++ 编程课程 - 初级到高级
该课程涵盖 C++ 编程的不同方面。
涵盖的主题:
-
设置 C++ 开发环境:这些视频概述了如何在各种平台上设置 C++ 开发环境。这包括安装不同的编译器以及配置 Visual Studio Code 以使用编译器和 C++ 标准库。这些说明涵盖 Windows、Mac 和 Linux 等平台。
-
C++ 编程基础知识:视频涵盖变量、数据类型、函数和流程控制语句等基本概念。它们解释了如何声明变量、定义函数以及使用循环和条件语句等控制结构。这些视频还介绍了注释和 C++ 中的主要函数等概念。
-
字符串操作:特定视频重点介绍在 C++ 中使用字符串。他们解释了如何使用 strcmp 和 strcat 等函数来比较和连接字符串。这些视频还演示了如何使用 strcpy 函数复制字符串。
-
数组:该视频介绍了 C++ 中数组的概念。它们涵盖了声明和初始化数组、使用指针访问元素以及打印字符数组等主题。
-
动态内存分配和指针:这些视频解释了如何在 C++ 中管理内存以及如何使用动态内存分配技术为程序分配额外的内存。它们涵盖了指针、内存映射和内存管理单元的概念。这些视频还讨论了如何安全使用指针、避免崩溃以及处理指向同一内存位置的多个指针。
-
函数模板和 lambda 函数:这些视频解释了如何使用 C++ 中的函数模板创建通用函数。它们演示了编译器如何根据传入的参数类型生成函数定义。此外,视频还介绍了 lambda 函数,这些函数是匿名函数,无需指定名称即可调用。他们解释了 lambda 函数的语法和返回类型规范。
-
类和继承:这些视频介绍了 C++ 中类的概念,并解释了如何在类中定义成员变量和函数。它们涵盖的主题包括构造函数、析构函数、访问说明符(受保护的和私有的)以及使用静态和动态绑定来实现多态性。这些视频还演示了如何使用继承基于预先存在的类来创建和使用派生类。
-
调试和错误处理:这些视频提供了有关调试 C++ 程序的指导。他们解释了如何设置断点、检查本地范围内的变量以及处理与未初始化指针和内存泄漏相关的错误。这些视频还涵盖了对象切片和重写基类构造函数等概念。
-
接口和多态性:一些视频重点介绍 C++ 中的接口和多态性。他们解释了如何使用动态绑定、引用和 override 关键字来实现程序中的多态行为。这些视频还讨论了 Final 说明符,它可用于将虚拟方法标记为 Final 并防止它在派生类中被重写。
-
其他主题:涵盖的其他主题包括默认参数、用于自动输出流打印的流可插入接口以及利用接口创建更具可读性的代码。
该视频提供分步说明、演示和解释,帮助初学者学习 C++ 编程,从安装和配置到更高级的概念,如面向对象编程、内存管理和多态性。内容既适合想要学习 C++ 编程基础知识的初学者,也适合想要刷新技能或深入探索特定主题的经验丰富的程序员。
代码:https: //github.com/rutura/The-C-20-Masterclass-Source-Code
第 1 章:设置工具
- 00:04:32 C++ 开发工具
- 00:11:06 在 Windows 上安装 C++ 编译器
- 00:24:27 在 Windows 上安装 VS Code
- 00:28:00 在 Windows 上为 C++ 配置 Visual Studio 代码
- 00:57:27 在 Linux 上安装 C++ 编译器
- 01:04:02 在 Linux 上安装 Visual Studio Code
- 01:07:40 在 Linux 上为 C++ 配置 Visual Studio Code
- 01:22:45 在 MacOS 上安装 C++ 编译器
- 01:28:07 在 MacOS 上安装 Visual Studio Code
- 01:30:16 在 MacOS 上为 C++ 配置 Visual Studio Code
- 01:35:37 在线编译器
第 2 章:深入研究
- 01:43:01 你的第一个 C++ 程序
- 01:55:56 评论
- 02:01:56 错误和警告
- 02:13:12 语句和函数
- 02:31:34 输入输出
- 02:49:57 C++ 程序执行模型和内存模型
- 02:56:42 C++核心语言VS标准库VSSTL
第 3 章:变量和数据类型
- 03:00:47 变量和数据类型介绍
- 03:05:05 数字系统
- 03:21:52 整数
- 03:40:44 整数修饰符
- 03:54:00 小数
- 04:16:39 布尔值
- 04:24:49 字符和文本
- 04:32:05 汽车
- 04:38:06 作业
- 04:45:42 变量和数据类型摘要
- 04:46:45 数据介绍操作
- 04:47:31 基本操作
- 04:58:01 优先级和关联性
- 05:12:06 前缀和后缀 + & -
- 05:23:22 复合运算符
- 05:31:43 关系运算符:比较东西
- 05:40:51 逻辑运算符
- 05:56:09 输出格式
- 06:33:26 数字限制
- 06:41:10 数学函数
- 06:54:23 奇怪的整体类型
- 06:59:41 数据操作总结
- 07:01:58 流程控制:条件编程简介
- 07:03:30 如果语句
- 07:20:49 否则如果
- 07:28:46 切换
- 07:42:44 三元运算符
- 07:52:20 流程控制:条件编程总结第 6 章:循环
- 07:53:49 循环介绍
- 07:55:20 For 循环
- 08:25:20 While 循环
- 08:36:54 执行 While 循环
- 09:53:23 指针介绍
- 09:56:03 声明和使用指针
- 10:14:48 指向 Char 的指针
- 10:27:26 程序内存映射
- 10:36:30 动态内存分配
- 11:05:45 悬空指针
- 11:24:15 当新的失败时
- 11:38:00 空指针安全
- 11:45:18 内存泄漏
- 11:55:44动态数组
- 12:44:29 字符操作和字符串介绍
- 12:46:24 角色操作
- 13:09:28 C 弦操作
- 13:41:42 C 字符串连接和复制
- 14:01:19 介绍 std::string
- 14:03:38 声明和使用 std::string
- 14:12:47 一种定义规则
- 14:28:25 亲身体验功能
- 15:00:50 函数声明和定义
- 15:15:30 跨多个文件的函数 - 重新审视编译模型
- 15:42:30 传递价值
- 15:50:30 通过指针
- 15:57:46 通过引用传递
第 13 章:函数重载
第 15 章:函数模板
第16章:概念
第17章:课程
- 20:15:40 课程介绍
- 20:16:33 你的第一个 C++ 课程
- 20:38:03 建设者
- 20:53:35 默认构造函数
- 20:59:42 设置器和吸气器
- 21:10:06 跨多个文件的类
- 21:30:49 通过指针管理类对象
- 21:42:48 析构函数
- 22:05:44 构造函数和析构函数调用顺序
- 22:11:03 This 指针
- 22:33:33 结构
- 22:42:37 类对象的大小
第18章:继承
- 22:52:43 继承介绍
- 22:55:59 你第一次尝试继承
- 23:21:10 受保护会员
- 23:32:06 基类访问说明符:放大
- 23:36:49 基类访问说明符:演示
- 24:07:42 接近私有继承
- 24:26:36 复活成员回到范围内
- 24:46:59 具有继承的默认 Arg 构造函数
- 24:57:37 具有继承性的自定义构造函数
- 25:26:56 具有继承的复制构造函数
- 25:51:53 继承基础构造函数
- 26:06:00 带有析构函数的继承
- 26:12:20 继承中重用符号
第19章:多态性
- 26:21:03 多态性介绍
- 26:26:54 静态绑定与继承
- 26:55:24 具有虚函数的多态性(动态绑定)
- 27:14:31 多态对象的大小和切片
- 27:26:37 存储在集合中的多态对象
- 27:45:42 覆盖
- 27:52:45 重载、覆盖和隐藏
- 28:07:35 不同级别的继承和多态性
- 28:33:03 静态成员的继承和多态性
- 28:49:13 决赛
- 29:07:42 具有默认参数的虚拟函数
- 29:23:18 虚拟析构函数
- 29:35:38 Dynamic_cast<>()
- 30:08:17 不要从构造函数和析构函数调用虚拟(多态)函数
- 30:24:45 纯虚函数和抽象类
- 30:43:37 抽象类作为接口
- 2022.02.17
- www.youtube.com
数据结构简单到高级课程 - 来自 Google 工程师的完整教程(第 1-4 部分)
数据结构从简单到高级课程 - 来自 Google 工程师的完整教程
简要总结:
00:00:00 - 01:00:00 讲师解释数据结构及其在创建更快、更强大的算法方面的重要性。本教程介绍了 Big O 表示法以及如何使用它来标准化算法所需的时间和空间,并针对不同的时间复杂度提供了具体示例。本教程还介绍了静态和动态数组的实现,包括它们的优点和缺点,并深入研究了在单链表和双链表中创建和插入节点。最后,本教程介绍了堆栈数据结构并简要解释了其主要操作。
01:00:00 - 02:00:00 “数据结构简单到高级课程”教程的这一部分全面介绍了各种数据结构及其功能。该教程引导观众了解堆栈和队列的工作原理、它们使用数组和链表的实现,以及它们在不同应用程序中的重要性,包括图形遍历和管理服务器请求。本教程还探讨了优先级队列及其使用堆的实现,阐明了优先级队列和堆之间的区别以及堆的类型。本教程最后提供了如何在二进制堆中添加和删除元素的分步演示。
02:00:00 - 03:00:00 Google 工程师提供了有关数据结构的完整教程,解释了如何从二元堆数据结构中删除节点、如何维护优先级队列中的堆不变量以及如何游动和二叉堆数据结构中的接收节点。该视频还介绍了并集查找数据结构,该结构用于跟踪分为不相交集合的元素并将两个组合并在一起,并以有关磁铁的示例来说明数据结构的工作原理。此外,还解释了 Kruskal 在图中查找最小生成树的算法,并引入了路径压缩的概念以使并查找数据结构更加高效。
03:00:00 - 04:00:00 本教程涵盖各种数据结构,从并查找数据结构及其方法开始,包括 find、connected、parent、size 和 unify。然后本教程转向树,包括树、有根树、二叉树和二叉搜索树的定义。该视频提供了从二叉搜索树中插入和删除节点的示例,以及不同的遍历算法,包括前序、中序、后序和层序,并解释了如何在 Python 和 Java 中实现这些结构。此外,该视频还介绍了哈希表,并讨论了哈希函数和流行的冲突解决方法的重要性。
04:00:00 - 05:00:00 本节涵盖哈希表及其实现的各个方面。它讨论了哈希函数(将键映射到值)的重要性,以及如何使用单独链接和开放寻址等技术来处理哈希冲突。本教程还介绍了在哈希表中插入、删除和搜索条目的方法,以及调整大小和管理负载因子的方法。演讲者强调了选择适当的探测函数和表大小以避免无限循环和性能问题的重要性。本教程使用实际示例来说明概念。
05:00:00 - 06:00:00 本节全面概述冲突解决中的哈希表、双重哈希和二次探测。该视频涵盖了调整哈希表大小和增长哈希表、处理冲突和删除以及使用二次探测实现哈希表的概念。视频还介绍了 Fenwick 树,这是一种数据结构,支持对数时间范围查询和点更新,构建时间为线性。该视频逐步说明如何使用 Fenwick 树执行前缀和和范围查询。
06:00:00 - 07:00:00 该视频教程涵盖了各种主题,包括用于快速范围查询和点更新的 Fenwick 树的概念,使用后缀数组和 LCP 数组查找唯一子串和最长公共子串,以及求解使用滑动窗口技术的最长公共子串问题。本教程还解释了如何使用 LCP 数组有效地找到最长的重复子串,并探讨了平衡二叉搜索树(特别是 AVL 树)的属性和重要性,以及如何通过使用树旋转来保持它们平衡。该视频提供了详细的解释、示例以及 GitHub 上提供的 Java 源代码。
第1部分
- 00:00:00 演讲者介绍了数据结构的概念,作为一种有效组织数据的方式,以及它们对于创建更快、更强大的算法的重要性。演讲者谈到了了解如何以及何时为手头的任务使用适当的数据结构的重要性,以及数据结构如何使代码更清晰、更容易理解。还解释了抽象数据类型的概念,并举例说明了抽象数据类型如何仅提供接口,而不提供有关如何实现数据结构的具体细节。此外,该视频还简要介绍了计算复杂性,以了解数据结构的性能。
- 00:05:00 引入 Big O 表示法的概念是为了标准化算法根据最坏可能的输入排列运行所需的时间和空间。 Big O 只关心当输入变得非常大时会发生什么,并删除添加到 Big O 符号中的常数值。还引入了函数f的概念,并且指出n的f的Big O只是n的三次方,这是该函数中最大、最具主导性的项。
- 00:10:00 Google 工程师提供了如何使用 Big O 表示法的具体示例。这些示例根据时间复杂度进行分类——恒定时间、线性时间、二次时间、对数时间。他还通过二分搜索的示例逐步详细介绍了如何实现对数时间复杂度。此外,他还演示了如何计算更复杂算法的时间复杂度,并解释了确定算法复杂度的规则。
- 00:15:00 演讲者讨论了具有外循环和内循环的嵌套循环的复杂性分析。内循环的工作量恒定,外循环的工作量可变。该函数的大 O 是 O(n^4),因为 n^3 是主项。然后,演讲者介绍了静态数组,它是一个固定长度的容器,其中包含可索引元素,这些元素是连续的内存块。静态数组随处可见,从临时存储对象到存储来自输入或输出流的信息。演讲者概述了数组的基本结构、可以对其执行的常见操作及其复杂性分析。
- 00:20:00 讲师讨论了数组在编程中的使用,包括作为仅允许一个返回值的语言和动态编程中的一种解决方法。他解释说,由于数组的可索引属性,其访问时间是恒定的,但在最坏的情况下,搜索可能会花费线性时间。从静态数组中插入、追加和删除是不可行的,但对于动态数组,调整内部数组的大小以进行追加会导致罕见但恒定时间的操作。最后,他指出可以使用 for-each 循环来迭代元素,并且计算机科学中的数组索引从零开始,这可能会让一些初学者感到困惑。
- 00:25:00 该视频讨论了数组中索引的概念,其中方括号表示索引,以及动态数组如何根据需要增长和收缩,从而允许与静态数组类似的 get set 操作。为了实现动态数组,使用静态数组,当超出容量时,数组大小加倍,并将所有元素复制到新的静态数组中。该视频还显示了数组类的源代码,该类支持 T 类型的泛型,并具有内部静态数组、长度和容量的实例变量。
- 00:30:00 讲师介绍了动态数组的多种方法的实现,包括 size、inset、clear、add、remove、index of、contains 和 toString。 add 方法涉及在达到容量时通过将其大小加倍来调整数组大小,remove 方法使用两个索引来复制数组中除删除索引之外的所有元素。讲师还演示了如何为动态数组创建迭代器,并讨论使用迭代器迭代数组元素的好处。总的来说,本教程简单而全面地介绍了动态数组的实现。
- 00:35:00 讲师介绍了单链表和双向链表,解释说它们是保存数据并指向包含数据的其他节点的节点的顺序列表。链表用于实现列表、堆栈和队列,以及循环列表、散列表单独链接以及邻接列表和图。讲师还介绍了一些创建链接列表的有用术语。此外,还讨论了单链表和双向链表的优缺点,单链表内存效率更高,但缺乏访问先前元素的能力,而双链表可以向后遍历并允许轻松删除节点。
- 00:40:00 讲师讲解了在单链表和双向链表中创建和插入节点的实现细节。要在单向链表中插入节点,将创建一个新指针,并将遍历器指针前进到所需位置,然后创建新节点并将其链接到其他节点。另一方面,双向链表同时具有next和previous指针,当插入新节点时,相邻节点和新节点的指针都需要更新。从单链表中删除节点涉及使用两个指针前进并删除所需的节点,然后稍后释放其内存。
- 00:45:00 演讲者介绍了如何从双向链表中删除节点,这比从单链表中删除节点更容易,因为我们不必手动维护对最后一个节点的引用。演讲者展示了 Java 实现,并讨论了链表中各种操作的复杂性,例如从头部或尾部搜索和删除元素。虽然在最坏的情况下在链表中搜索是线性的,但插入到头部或删除头部是常数时间。在单链表中,从尾部删除需要线性时间,但在双向链表中则不需要,因为它具有对前一个节点的引用。
- 00:50:00 在视频的这一部分中,演示者解释了双向链表的实现,以及清除列表、获取大小和检查是否为空以及向列表的开头和结尾添加节点的方法。他还解释了如何查看列表的第一个或最后一个元素、删除第一个或最后一个元素以及删除列表中间的任意节点。演示者强调了正确释放内存的重要性,并将节点类设置为私有以防止用户直接访问它。
- 00:55:00 在视频的这一部分中,导师解释了如何从链表中删除特定索引的节点,即使这些节点没有明确索引。 Remove 方法支持从链表中删除任意值并搜索空值。导师还解释了用于获取链表中对象索引的索引方法和迭代器方法。最后,导师介绍了堆栈数据结构,并简要概述了其主要操作:入栈和出栈。导师还强调,该系列中即将推出的视频将涵盖堆栈实现、使用堆栈解决的问题以及与堆栈操作相关的时间复杂度。
第2部分
- 01:00:00 该视频讨论了堆栈数据结构的功能及其在编程中的各种用途。该视频提供了如何在堆栈中添加和删除操作的详细示例,并解释了如何在文本编辑器、编译器和支持递归中使用堆栈。此外,该视频还重点介绍了如何使用堆栈对图执行深度优先搜索,并提出了如何使用堆栈确定括号序列是否有效的一个很酷的示例问题。最后,该视频包括堆栈的复杂性分析以及它们如何作为链表发挥作用。
- 01:05:00 Google 工程师演示了如何使用堆栈数据结构检查括号序列是否有效。他一步一步地执行算法,将左括号压入堆栈,遇到右括号时将其弹出,并检查它们是否匹配。他还解释了河内塔游戏如何与堆栈相关,因为每个钉子代表一个堆栈,而圆盘代表只能在特定条件下移动的元素。最后,他讨论了如何使用数组或链表来实现堆栈。
- 01:10:00 我们学习如何使用单链表创建堆栈,并通过 Java 编程语言中堆栈数据结构的简单实现从堆栈中弹出元素。堆栈是通过将头指向空节点来创建的,这意味着堆栈为空。新元素插入到头之前,弹出元素是通过将头指针移动到下一个节点并释放最后一个节点来完成的。数据结构中的内存泄漏可能会导致问题,因此在所有数据结构中警惕它们并在必要时纠正它们非常重要。
- 01:15:00 讲师讨论队列,这是一种线性数据结构,用于模拟现实世界的队列,具有两个主要操作:入队和出队。队列的前部和后部分别用于插入和删除元素。讲师还解释了有关队列的各种术语,入队有时称为添加,出队称为轮询或从队列前面删除。队列的一个典型示例是电影院或餐厅的排队,队列可用于跟踪序列中的 x 个最新元素。
- 01:20:00 该视频解释了如何使用队列来管理服务器请求以及如何在图上进行广度优先搜索遍历。引入了请求排队的概念,空闲的服务器一次只能处理一定数量的请求,任何多余的请求都会放入队列中。该视频还介绍了广度优先搜索的基础知识,其中按照距起始节点的距离的顺序访问图的节点。该视频最后解释了使用队列数据结构实现 n 排队和出队元素。
- 01:25:00 本教程深入研究了队列,并解释了如何使用数组或不同类型的链表(单链表和双链表)来实现队列抽象数据类型。本教程提供了一个示例,说明队列的单链表实现如何工作,并讨论了使用 Java 编程语言实现各种队列方法(如peak、poll 和 Offer)。本教程还在 github.com 上分享了队列实现源代码的链接。
- 01:30:00 在本教程的这一部分中,Google 工程师解释了数据结构的概念和实现,特别是队列和优先级队列。他讨论了优先级队列的操作方式与普通队列类似,唯一的区别是每个元素都有一定的优先级,优先级较高的元素首先从队列中出来。他还强调,优先级队列只支持可比较的元素,这意味着我们插入优先级队列的数据必须是有序的。此外,他还提供了一个示例来解释轮询和将元素添加到优先级队列的操作。在本教程的下一部分中,他将更详细地介绍对优先级队列执行的常见操作、将最小优先级队列转换为最大优先级队列、复杂性分析以及实现优先级队列的方法。
- 01:35:00 Google 工程师解释了如何使用堆实现优先级队列。堆是一种基于树的数据结构,满足堆不变量,这意味着对于所有节点来说,父节点的值始终大于或等于子节点的值,从而产生两种类型的堆: 最大堆和最小堆。堆很重要,因为它们构成了优先级队列的规范底层数据结构。然后,Google 工程师展示了结构示例,并询问观众它们是否是堆,证明所有堆都必须是树并且满足堆不变量。
- 01:40:00 讨论了优先级队列在Dijkstra最短路径算法和霍夫曼编码等算法中的重要性。优先级队列在需要动态获取下一个最佳或最差元素的情况下非常有用。主要关注的是作为二叉堆实现的优先级队列,以及操作,包括添加元素、删除元素、检查包含性以及将最小优先级队列更改为最大优先级队列。哈希表可用于将移除时间复杂度提高到对数,而朴素方法则对所有元素进行线性扫描。本节最后介绍了将最小优先级队列转换为最大优先级队列的技巧。
- 01:45:00 Google 工程师解释了如何使用否定作为在优先级队列中实现反向堆的简单方法。他提供了使用带有标准词典比较器和否定比较器的最小优先级队列进行数字和字符串操作的示例。工程师还介绍了二叉堆的概念以及如何向其中添加元素。
- 01:50:00 讲师解释了理解如何使用二进制堆将元素有效添加到优先级队列所需的重要术语和概念。他澄清说,优先级队列不是堆,而是一种抽象数据类型,它定义了优先级队列应具有的行为,而堆只是让我们实际实现该行为的数据结构。他还讨论了堆的类型,包括二叉堆,并解释了完整的二叉树属性以及如何使用数组构造来表示二叉堆。
- 01:55:00 Google 工程师解释了如何将节点添加到二进制堆并通过使用一种轻松访问节点的子节点和父节点的技术来维护堆不变式。他们以将值插入最小堆的示例进行说明,并演示如何冒泡节点以满足堆不变量。在下一节中,工程师将介绍从二叉堆中删除元素,并强调删除根值(具有最高优先级的感兴趣节点)的重要性。
第三部分
- 02:00:00 Google 工程师解释了使用 pull 方法从二进制堆数据结构中删除节点的过程。拉动在两种情况下完成,即删除根节点和删除特定节点时。当删除根节点时,该节点与数组中的最后一个节点交换,并通过向下冒泡来保证堆不变性。当删除特定节点时,线性搜索该节点,与堆中的最后一个节点交换,然后根据交换节点的值通过向上或向下冒泡来确保堆不变性。工程师得出的结论是,拉动对于根节点来说需要对数时间,对于特定节点来说需要线性时间。
- 02:05:00 在本教程的这一部分中,Google 工程师解释了如何通过使用哈希表来删除堆中的节点并提高时间复杂度。每个节点都映射到它所在的索引,而不是进行线性扫描来查找要删除的节点的索引。当我们想要删除一个特定的节点时,我们只需查找它的索引即可开始执行操作。该视频还介绍了如何处理堆中多个值的问题以及如何跟踪树中值的位置。工程师解释说,只要我们满足堆不变量,删除哪个节点并不重要。本教程包括使用提出的新方案添加、拉动和删除元素的示例。
- 02:10:00 演讲者解释了如何使用堆数据结构在优先级队列中插入、删除和维护堆不变量。然后他深入研究源代码并重点介绍实现优先级队列所需的一些重要实例变量和构造函数。他解释说,优先级队列中允许的元素必须实现可比较的接口,并且可以使用将元素映射到表示堆中元素位置的一组整数的映射来跟踪日志记录和删除。
- 02:15:00 在本教程的这一部分中,Google 工程师讨论了创建优先级队列的不同方法,包括创建具有设定容量的初始为空的队列、创建具有定义的初始容量的队列以及以线性方式构造队列使用 heapify 操作的时间。工程师还介绍了优先级队列的一些简单方法,包括清空、清除、大小、查看、轮询和包含。还讨论了 add 方法,详细介绍了如何将元素添加到队列以及跟踪映射中元素的重要性。游泳功能也被突出显示为将元素添加到列表末尾后的必要步骤。
- 02:20:00 在视频的这一部分中,Google 工程师解释了在二进制堆数据结构中游动和下沉节点的方法。游泳方法涉及与其父节点交换节点并向上移动,直到节点根据其值位于正确的位置。下沉方法类似,但涉及将节点与其子节点进行比较,并与较小的节点进行交换,直到到达正确位置。工程师还讲解了二进制堆中实现的swap、remove、remove add方法。移除添加方法涉及将移除的节点与堆中的最后一个元素交换,并将新节点下沉或游动到适当的位置。
- 02:25:00 在本教程的这一部分中,讲师将解释如何从堆数据结构中删除节点,并根据交换是否影响堆的结构,使用下沉或游动节点的方法确保维护最小堆的完整性。命令。本节还介绍并集查找数据结构及其两个主要操作 find 和 union,它们分别用于跟踪划分为不相交集合的元素以及将两个组合并在一起。
- 02:30:00 演讲者以磁铁为例解释并查找数据结构的工作原理。并集查找有效地合并项目或项目组,并为它们分配任意颜色。并查找数据结构用于各种算法中,例如最小生成树算法和网格渗滤。 union find 具有出色的复杂性,并且其构造是线性时间的,而其计数组件函数可以在恒定时间内确定组件的数量,使其成为一种很好的数据结构。
- 02:35:00 在本教程的这一部分中,Google 工程师解释了用于在图中查找最小生成树的 Kruskal 算法。该算法包括按边权重升序对边进行排序,然后将不属于同一组的节点统一起来,直到所有顶点统一为一组。并查找数据结构用于有效地合并组并防止循环。工程师提供了一个示例图并逐步介绍该算法的步骤以说明其工作原理。
- 02:40:00 本教程解释了并集查找数据结构及其内部工作原理。第一步是创建对象和整数之间的映射(范围从 0 到 N(不包括在内)),其中 N 是元素的数量。然后构造一个数组,每个索引都有一个关联的对象,这是通过映射完成的。数组位置中的值最初是它所在的索引,每个节点都是映射到其自身的根节点。当执行指令将对象统一到组中时,数组中的值已更改为映射到其他对象。较小的组件被合并为较大的组件,根节点用于统一组。
- 02:45:00 演讲者谈论如何使用并集查找数据结构将元素合并到不同的组中。通过查找并跟踪每个组件根节点的父节点,我们可以确定元素属于哪个组件。为了统一两个组件,我们使一个根节点指向另一个根的父节点。组件的数量等于剩余根节点的数量,并且当我们统一组件时,根节点的数量只会减少。演讲者还指出,如果不使用路径压缩,该结构的实现目前不具有摊销时间复杂度,这一优化将在下一个视频中讨论。
- 02:50:00 引入路径压缩的概念来展示它如何使并集查找数据结构更加高效。路径压缩涉及压缩沿路径到根节点的所有节点,从而允许对任何给定组件的根节点进行恒定时间查找。给出了使用和不使用路径压缩来统一组的示例,以比较和对比两种方法,展示通过路径压缩获得的效率。
- 02:55:00 讲师讨论路径压缩和并集查找如何协同工作以创建高效的数据结构。他演示了路径压缩如何动态压缩路径直至达到最终状态。视频中展示了并集查找代码,并解释了如何使用数组来索引和跟踪父子关系。此外,该代码还包括检查根节点并压缩其路径的方法。讲师强调观看 union find 上的其他视频以充分了解该主题的重要性。
第 4 部分
- 03:00:00 讲师介绍并查数据结构及其方法,包括find、connected、parent、size和unify。他演示了结构的根节点如何包含每个连接组件的大小,以及 unify 方法如何将较小的组合并为较大的组。继续讨论树,讲师简要概述了作为无向图的树,并介绍了二叉树和二叉搜索树。他承诺在后续教程中介绍如何在二叉搜索树中插入和删除节点、树遍历以及如何将它们应用于一般树。
- 03:05:00 引入了树的概念,并提供了多种定义。树可以定义为连通且非循环的无向图、具有 n 个节点和 n-1 条边的图,或者任意两个顶点之间只有一条路径的图。还引入了有根树,其中任何节点都可以成为根,并且定义了子节点和父节点。根节点的父节点是其自身,叶节点被定义为没有子节点的节点。还引入了子树的概念,用树内的三角形表示。此外,二叉树的定义被解释为每个节点最多有两个子节点的树。
- 03:10:00 该视频介绍了二叉搜索树,即满足二叉搜索树不变量的二叉树。这意味着左子树的值始终小于当前节点,而右子树的值始终大于当前节点。该视频展示了二叉搜索树的各种示例,并要求观众确定他们是否满足不变量。二叉搜索树在抽象数据类型的许多实现中都很有用,并且用于平衡二叉搜索树和语法树。对于随机数据的插入和搜索等操作,它们在平均情况下也具有对数时间复杂度。
- 03:15:00 在本教程的这一部分中,Google 工程师讨论了二叉搜索树以及如何向其中插入元素。二叉搜索树平均具有对数行为,这使得它们在大多数情况下易于实现且高效。然而,在最坏的情况下,二叉树可以变成线性数据结构,这并不理想。要在二叉搜索树中插入元素,该元素必须是可比较的,并且可能会发生以下四种情况之一:左子树向下递归、右子树向下递归、处理重复值或插入新节点。最后,工程师演示了如何使用动画将值插入二叉搜索树。
- 03:20:00 Google 工程师解释了将值插入二叉搜索树时最坏的情况,这会导致它变成线性结构。这种行为是不可取的,因为它会减慢搜索节点或删除值等操作的速度。然后,工程师解释了如何分两步从二叉搜索树中删除元素:首先找到要删除的节点,然后用其后继节点替换它,以保持二叉搜索树不变。该视频提供了如何在二叉搜索树中搜索值的示例,以帮助理解该过程。
- 03:25:00 Google 工程师解释了处理二叉搜索树时删除阶段的四种情况。第一种情况是当要删除的节点是叶节点时,第二种和第三种情况发生在左侧或右侧只有一个子树时。第四种情况发生在节点同时具有左子树和右子树时,问题是该节点的后继者将在哪一个子树中?答案是,后继可以是左子树中的最大值,也可以是右子树中的最小值,并且可以有两个可能的后继。
- 03:30:00 在课程的这一部分中,讲师将解释如何使用后继节点的概念从二叉搜索树中删除节点。后继节点要么是右子树中的最小节点,要么是左子树中的最大节点。讲师通过几个例子演示了节点的移除,强调移除后重新平衡树的重要性。本节最后概述了不同的树遍历,包括前序、中序、后序和级别顺序。
- 03:35:00 讲师解释二叉树中前序、中序和后序遍历的概念。他解释说,预序打印当前节点的值,后跟其左子树和右子树,然后提供了一个示例,说明预序遍历如何在二叉树中工作,维护一个调用堆栈来跟踪访问了哪些节点。同样,他解释了中序遍历的工作原理,其中涉及遍历左子树,打印值,然后遍历右子树。讲师以二叉搜索树为例,重点介绍了遍历过程中访问和打印节点的顺序。
- 03:40:00 本教程讨论了二叉树的不同遍历算法。首先,中序遍历,按升序打印节点的值。接下来,后序遍历,先遍历左子树,然后遍历右子树,只有在遍历完这两个子树后,才打印该节点的值。本教程继续解释广度优先搜索以及如何将其用于级别顺序遍历,一次打印一层节点。队列用于跟踪要探索的节点,并且当访问其父节点时将节点添加到队列中。
- 03:45:00 在视频的这一部分中,讲师解释了如何使用队列数据结构执行广度优先搜索。他演示了探索节点并根据其子节点的顺序将其子节点添加到队列的过程。他强调了在执行层序遍历时使用队列而不是堆栈的重要性。然后,视频将重点转移到 Java 中二叉搜索树的实现,讲师解释了类结构、实例变量以及用于向树添加元素的方法。他还强调了在使用二叉搜索树时选择可比较类型的重要性。
- 03:50:00 讲师解释从二叉搜索树中删除节点的过程。他们首先讨论删除节点的公共方法,并解释说,只有在树中存在该节点时,他们才会删除该节点,这是首先检查的。然后,他们深入研究用于删除节点的递归方法,该方法涉及找到要删除的节点,然后根据它是否具有左子树和/或右子树来实际删除它。讲师解释了三种不同的删除情况,其中涉及左子树或右子树,或同时涉及左子树和右子树。它们还提供了用于遍历树以查找后继节点的辅助方法。
- 03:55:00 Google工程师讲解了如何用Python实现二叉搜索树,包括插入新节点、搜索特定元素以及计算树的高度。他还展示了如何使用名为“traverse”的自定义方法迭代地实现二叉树遍历,该方法将树遍历顺序作为输入并返回该顺序的迭代器。接下来,他介绍了哈希表并讨论了哈希函数的重要性,以及流行的冲突解决方法,例如单独链接和开放寻址。
- 2019.09.19
- www.youtube.com
数据结构从简单到高级课程 - 来自 Google 工程师的完整教程(第 5-8 部分)
数据结构从简单到高级课程 - 来自 Google 工程师的完整教程
第五部分
- 04:00:00 讲师介绍哈希表的概念及其使用哈希技术的实现。哈希表用于构造从键到值的映射,其中每个键都是唯一的并与一个值关联。为了将键映射到值,使用哈希函数,该函数将键映射到某个固定范围内的整数。讲师演示如何使用字符串中字符的 ASCII 值为任意对象(例如字符串)定义哈希函数。哈希表通常用于跟踪值的频率并构建键值对之间的映射(前提是键是可哈希的)。本节以一个小挑战结束,即为具有三个字段的人员数据库定义哈希函数。
- 04:05:00 讲师讨论哈希函数及其属性。哈希函数是任意定义的,并且可以有无限多种可能性。讲师强调哈希函数必须是确定性的,以避免搞乱哈希表。哈希函数的一致性对于最大限度地减少当两个对象哈希为相同值时发生的哈希冲突也很重要。讲师还说明了哈希值如何加速对象比较,并继续解释复杂的哈希函数(例如加密哈希函数和校验和)用于文件,而不是用于哈希表的哈希函数。
- 04:10:00 本教程解释了如何使“t”类型的键可散列,以及散列表如何使用统一散列函数对其进行索引。它提到哈希函数需要具有确定性,并强制使用固定且恒定的不可变键,例如不可变字符串和整数。通过使用哈希函数作为哈希表的索引方式,我们可以在恒定时间内实现快速插入、查找和删除。本教程还提供了一个将键值对插入到表中最终导致哈希冲突的示例,并解释了如何处理冲突。
- 04:15:00 演讲者讨论了哈希冲突解决技术,特别是单独的链接。单独链接是一种处理哈希冲突的方法,它通过维护辅助数据结构(通常是链表)来保存哈希为特定值的所有不同键值对。哈希表的时间复杂度平均可以实现恒定时间的插入、删除和搜索,但是如果哈希函数不均匀,则可能是线性时间。演讲者还提供了一个示例,说明单独链接如何工作,以及如何通过为数组中的每个索引维护链表数据结构,使用它来处理哈希表中的冲突。
- 04:20:00 演讲者解释了如何在具有单独链接的哈希表中进行查找,该哈希表使用链表来处理冲突。对于给定的键,演讲者演示如何通过对键进行哈希处理并在哈希表的相应桶中搜索链表来找到相应的值。演讲者还解决了一些常见问题,例如保持恒定的时间复杂度、删除键值对以及使用不同的数据结构来处理哈希表中的存储桶。最后,演讲者分享了一些使用单独链接实现哈希表的源代码。
- 04:25:00 该视频介绍了哈希表以及它们如何在 Java 中实现。首先讨论入口类,重点讨论泛型、哈希码和 equals 方法。然后解释哈希表本身,包括最大负载因子、容量、阈值等实例变量和表本身(这是一个链表数组)。还讨论了各种方法,例如 size、empty、clear、contains key 和 hash 及其实现细节。最后解释一下归一化索引方法,该方法用于将哈希值转换为索引,以便在哈希表中查找。
- 04:30:00 在视频的这一部分中,演讲者解释了实现哈希表所涉及的方法,例如插入、获取、删除、查找条目和调整表大小。 insert 方法向哈希表添加一个新条目或更新现有条目,而 get 则检索与特定键关联的值。删除从哈希表中删除键值对,而查找条目方法有助于查找给定存储桶索引处的条目。最后,resize table 通过将其容量加倍来调整表的大小,然后使用新容量创建一个新表,将数据从旧表移动到新表,并删除旧数据。
- 04:35:00 讲师讨论解决哈希表中冲突的开放寻址技术。此方法将键值对存储在表本身中,而不是辅助数据结构中。因此,管理哈希表的大小和其中元素的数量至关重要。负载因子(即项目与表大小的比率)需要保持在某个阈值以下,以防止其变得呈指数级恶化。当插入新密钥时,哈希函数会给出该密钥的原始位置,但如果发生冲突,则会使用探测序列来查找下一个空位。线性探测序列是众多可供选择的序列之一。
- 04:40:00 讲师讨论开放寻址,这是一种处理散列表中冲突的方法,其中当原始散列索引已被占用时,项目被放置在不同的位置。引入了各种探测函数,例如线性探测、二次探测、双重哈希和伪随机数生成器探测函数,每种探测函数都使用不同的数学公式来查找下一个槽。然而,开放寻址的主要困难是可能产生比哈希表大小短的周期,这可能导致无限循环。举一个实际例子来说明这个问题。
- 04:45:00 演讲者讨论了哈希表中使用的探测函数的循环问题以及如何处理它。演讲者解释说,线性探测、二次探测和双重散列等技术都受到循环问题的影响,但可以重新定义以产生长度循环,以避免在插入元素时陷入无限循环。线性探测中的常数“b”被认为是过时的,并且演讲者提到某些线性函数可能无法产生“n”阶的完整循环。该问题的解决方案是选择探测函数,通过确保常数“a”和表大小“n”互质,产生恰好为“n”的循环。
- 04:50:00 讲师讨论哈希表及其工作原理,包括探测函数、表大小、负载因子和调整大小。他使用线性探测的示例来演示如何将键值对插入哈希表并避免哈希冲突导致的无限循环。然而,他指出,探测函数和表大小的选择会显着影响性能,并且选择与表大小最大公约数不同的函数可能会导致循环并引发问题。
- 04:55:00 我们看到一个使用探测函数将键值对插入哈希表而没有任何冲突的示例。如果确实发生碰撞,探测功能将继续探测,直到找到空点,以避免发生任何循环。一旦元素数量超过表的阈值,表大小就会加倍,同时保持 GCD 为 N。然后使用新表大小将旧元素放置在新表中,同时保持相同的探测函数。最后,插入一个新的键值对,如果该位置是空闲的,则没有问题。
第 6 部分
- 05:00:00 讲师讨论哈希表中的二次探测,它用于解决开放寻址中的冲突。这涉及使用选择随机探测函数根据二次公式进行探测。讲师解释说,并非所有二次函数都是可行的,因为它们不会产生顺序循环,从而导致陷入无限循环,但大多数随机选择的二次函数最终都会产生循环。讲师提供了三种最流行的方法来选择探测函数,并重点介绍第二种方法,其中 x 的 p 等于 x 平方加 x 除以 2,并且表大小为 2 的幂。
- 05:05:00 演讲者讨论了使用双重散列和开放寻址冲突解决技术将元素插入散列表的过程。他们解释了表大小是 2 的幂的重要性以及如何使用探测来处理冲突。演讲者还演示了当负载因子超过某个阈值时调整表大小的过程。他们继续讨论如何更新现有元素以及如何将新元素插入表中。
- 05:10:00 讲师解释了双重哈希的概念,这是一种用于处理哈希表中冲突的探测方法。双散列方案涉及根据另一个散列函数(称为辅助散列函数)的常数倍进行探测。讲师警告双重哈希情况下可能出现的无限循环问题,并提供了解决该问题的策略,其中包括为表大小选择一个质数并构造一个称为 delta 的值。他还讨论了使用相同的基本构建块为不同数据类型生成新哈希函数的系统方法。
- 05:15:00 演讲者解释了哈希函数的概念以及如何将它们组合起来创建新的哈希函数。他们提到了通用哈希函数的使用,并提供了使用双重哈希的示例。他们讨论了将键值对插入哈希表的过程,同时还处理哈希冲突和更新。该示例使用的表大小为 7,最大负载因子为 0.75,哈希函数使用整数和实数作为构建块。
- 05:20:00 本教程解释了使用双重哈希调整哈希表大小和增长哈希表的过程,其中包括将表大小加倍、查找高于该值的下一个质数、分配新表以及将旧元素插入新表桌子。本教程提供了一个示例,其中原始表在插入 5 个元素后已达到其最大阈值,并且表大小调整为新大小 17。本教程还探讨了使用开放寻址从哈希表中删除元素时出现的问题方案,以及在插入和删除操作期间避免冲突的重要性。
- 05:25:00 该视频解释了如何处理哈希表中的哈希冲突和删除。简单的删除方法(仅清除存储桶的内容)被证明是有缺陷的,因为它会影响在哈希表中正确查找元素的能力。相反,视频建议放置一个称为墓碑的独特标记来代替已删除的元素。该标记稍后可以替换为新的键值对,或者在调整哈希表大小期间删除。该视频提供了一个使用二次探测的示例来展示在哈希表查找过程中如何使用逻辑删除。
- 05:30:00 Google 工程师概述了使用开放两个地址作为冲突解决方案的哈希表。工程师讨论了延迟删除或延迟重定位,其中涉及重新定位键值对以避免在探测时遇到一堆逻辑删除。该工程师还提供了使用二次探测的哈希表的代码演练,其中涉及将键值对直接存储在数组内,而不是使用一个带有条目包装类的数组。工程师探索了哈希表的构造函数和默认常量,这允许用户在没有任何参数的情况下对其进行初始化。
- 05:35:00 在课程的这一部分中,讲师解释了如何使用二次探测来实现哈希表。该方法包括计算阈值、标准化索引和初始化表。提供插入方法信息,其中将键值对插入到哈希表中,或者如果键已存在则进行更新。讲师还讨论了键计数、哈希表的空检查以及在进入插入方法之前的加法。详细解释了插入键的 do-while 循环。
- 05:40:00 讲师解释了哈希表实现的 contains key、has key、get 和 remove 方法。 contains key 和 has key 方法通过调用 get 方法来检查哈希表中是否存在某个键,该方法为 contains 标志返回 true 或 false 值。 get方法查找哈希索引并查找键。如果该键存在,则 contains 标志设置为 true,并返回该值。删除方法更简单,首先在哈希表中找到键,然后递减,并在其位置转储墓碑。当插入新元素以增加表大小时,将调用 resize table 方法,其中分配新表,并将当前表与新表交换以调用 insert 方法。
- 05:45:00 芬威克树(也称为二叉索引树)是作为一种数据结构引入的,用于有效计算数组上的范围查询并执行点更新。芬威克树背后的动机是计算数组中的范围时线性查询效率低下。通过计算数组的所有前缀和,可以在常数时间内计算范围查询。然而,对数组的更新需要重新计算所有前缀和,从而使得该过程效率低下。芬威克树就是为了解决这个问题而创建的,它支持对数时间内的范围查询和点更新以及线性构建时间。芬威克树的工作原理是让每个单元根据其最低有效位的值负责一系列其他单元。
- 05:50:00 在视频的这一部分中,讲师讨论 Fenwick 树以及它们如何进行范围查询。他展示了一个图表,其中包含一个基于 1 的数组以及每个数字的二进制表示形式。该图显示了负责其自身的最低有效位,以及负责 2、4、8 或 16 个单元范围的所有其他单元。为了执行范围查询,讲师解释了如何通过向下级联直到达到零来计算达到特定索引的前缀总和。他演示了如何查找特定索引的前缀和以及如何在两个给定索引之间进行区间和。
- 05:55:00 我们学习如何使用级联效应计算前缀和以及如何使用 Fenwick 树执行范围查询算法。前缀和计算涉及从给定索引开始,从该值中减去最低有效位,直到达到零,然后在每次减法期间将所有值相加。范围查询算法使用 Fenwick 树,我们在其中获取范围查询的前缀和之间的差异。该算法需要位操作,并提供了一个简洁的小算法以加快计算速度。视频作者建议查看之前的 Fenwick 树范围查询视频,以了解有关如何设置树以及如何对其执行操作的更多上下文。
第7部分
- 06:00:00 Google 工程师解释了点更新和 Fenwick 树构建的概念。点更新涉及将值添加到树中的特定索引处,并查找负责该责任范围的单元格。同时,芬威克树的线性构造涉及通过将值传播到整个树的适当位置来更新负责值的直接单元,从而产生功能齐全的芬威克树。传播过程依赖于更新负责特定值的父级的级联思想。
- 06:05:00 在本教程的这一部分中,详细解释了 Fenwick 树的概念。芬威克树是一种数据结构,用于快速执行值数组的范围查询和点更新。该数据结构使用一种二进制索引,其中每个单元负责将其值传播到其父单元,依此类推。还讨论了 Fenwick 树的构造算法,该算法涉及通过克隆原始数组并计算新树结构中每个元素的父单元,将值数组转换为 Fenwick 树。显示了 Java 中 Fenwick 树实现的源代码,并且可在 GitHub 存储库中获取。
- 06:10:00 讲师解释如何创建 Fenwick 树类及其不同的构造函数。他还解释了前缀和,它允许计算从 1 到 i(含)的前缀和。该视频还介绍了如何从点更新添加以及将索引设置为等于 k 的附加方法。讲师强调使用二进制操作和后缀数组数据结构的重要性,这在字符串处理中非常有用。
- 06:15:00 介绍了后缀和后缀数组的概念,并以构建单词“camel”的后缀数组为例。后缀数组是一个排序索引数组,允许对排序后缀进行压缩表示,而无需存储后缀本身,使其成为后缀树的节省空间的替代方案。最长公共前缀 (LCP) 数组存储两个已排序后缀彼此共有的字符数,也作为与后缀数组相关的重要信息进行介绍,并举例说明了为给定的字符串构造 LCP 数组细绳。
- 06:20:00 该视频讨论了后缀数组和 LCP 数组在查找和计算唯一子字符串方面的应用,其方式比需要大量空间的朴素算法更有效。通过使用 LCP 阵列内存储的信息,它不仅提供了快速而且节省空间的解决方案。 LCP 数组表示原始字符串的两个相邻后缀之间共享的字符数。通过检查 LCP 值,可以确定哪些子串是重复的,并消除它们以有效地计算所有唯一子串。
- 06:25:00 演讲者讨论了寻找 n 个给定字符串中至少 k 个之间共享的最长公共子串的问题。解决这个问题的一种方法是动态编程,但它很快就会变得笨拙。更好的方法是使用后缀数组,它可以在线性时间内找到解。为此,演讲者解释说,我们首先将所有字符串连接成一个更大的字符串,在每个字符串之间添加唯一的标记值,以避免后缀的任何混合。然后,我们为这个连接字符串构造后缀数组,这使得我们可以通过查找共享最大LCP值的不同颜色的K个字符串来找到K个字符串的最长公共子串。
- 06:30:00 该视频教程讨论了如何使用滑动窗口技术查找字符串中 k 种不同颜色的最长公共子串。方法是调整窗口大小以包含k个不同颜色的后缀,并查询该范围内的最小LCP值。最小范围查询可以使用线性解决方案或最小范围查询数据结构(例如线段树)来解决。本教程还建议使用哈希表来跟踪窗口中的颜色。滑动窗口向下扩展以捕获缺失的颜色,并在满足条件时缩小。
- 06:35:00 在视频的这一部分中,讲师演示了使用后缀数组解决最长公共子串问题的示例。窗口LCP和窗口LCS值有助于跟踪当前窗口的最长公共前缀和最长公共子串值,而LCS长度和LCS集跟踪迄今为止的最佳值。该示例使用四个字符串和四个字符串池中的至少两个字符串来共享最长的公共子字符串。讲师演示了如何在搜索最长公共子串时扩大和缩小窗口,并提示观众要在演员网站上查看挑战,并在 GitHub 上提供算法实现的链接。
- 06:40:00 该视频解释了使用滑动窗口技术解决最长公共子串问题的过程。该算法通过扩大和缩小窗口大小并使用最长公共前缀数组来识别公共子串,以线性时间复杂度找到解决方案。然后,视频介绍了最长重复子串问题,并解释了如何使用最长公共前缀数组来有效地找到给定字符串中的最长重复子串,与需要 N 平方时间和大量内存的简单方法相比。
- 06:45:00 Google 工程师教授如何使用后缀数组和 LCP 数组来查找最长的重复子字符串。索引处的 LCP 值给出了两个相邻后缀之间最长公共前缀的长度。 LCP 数组中的最大值给出了最长重复子串的长度。在平局的情况下,必须找到所有可能的最长值。然后,工程师解释了平衡二叉搜索树的重要性,以及它们与传统二叉搜索树的不同之处在于,平衡二叉搜索树能够自我调整以保持相对于它们所持有的节点数量的对数高度,从而使得插入和删除速度非常快。实现这一点的关键概念是树旋转,它们将在视频中进一步讨论。
- 06:50:00 解释了平衡二叉搜索树中树不变性和树旋转的概念。树不变量是强加在树上的规则,在每次操作结束时都要满足,这是通过应用一系列树旋转来确保的。树旋转是合法的变换,如果保持节点的排序和位置,则在树中的节点周围移动而不会破坏二叉搜索树不变式。详细解释了右旋转的过程,并讨论了当节点同时引用子节点和父节点时更新指针所涉及的步骤。
- 06:55:00 该视频教程重点演示如何使用树旋转技术将节点插入 AVL 树,同时还解释了保持 AVL 树平衡的属性。首先,视频解释了什么是 AVL 树以及它作为第一种平衡二叉搜索树的意义。然后,视频介绍了平衡因子,即右子树和左子树的高度之差。视频强调每个节点的平衡因子要么是负一,要么是零,要么是加一,以维持AVL树的平衡。然后,本教程继续讨论如何处理情况并非如此,这可以通过树旋转来解决。
第 8 部分
- 07:00:00 讲师解释平衡 AVL 树中左重树所需的四种不同的旋转情况。讲师还提供了将节点插入 AVL 树的伪代码,并解释了更新和平衡方法。 update方法计算节点的高度和平衡因子,而balance方法检查节点的平衡因子是否违反AVL树属性并确定适当的旋转以重新平衡树。左-右和右-左情况也得到了解释,因为它们在第一次旋转后减少为左-左和右-右情况。
- 07:05:00 该视频解释了如何从 avielle 树中删除元素,这与从常规二叉搜索树中删除元素非常相似。删除过程可以分为两个步骤:找到该元素并用后继节点替换它以保持二叉搜索树不变。查找节点涉及将目标元素与树中的节点进行比较,直到找到匹配项或搜索到达树的末尾。替换过程取决于要删除的节点是叶节点还是只有左子树或右子树,后两种情况下后继节点是直接子节点。
- 07:10:00 讲师解释了如何从二叉搜索树中删除节点,并提供了三种删除情况的示例。第一种情况是当要删除的节点没有子节点时,第二种情况是当它有一个子节点时,最后一种情况是当它有两个子节点时。讲师还解释了如何通过简单地添加两行代码来增强 AVL 树的二叉搜索树删除方法,以确保树保持平衡并且平衡因子和高度值保持最新。最后,讲师提供了 GitHub 存储库的链接,观众可以在其中找到 AVL 树的源代码以及 AVL 树的实时演示。
- 07:15:00 讲师解释了 Java 中递归 AVL 树实现的源代码。 AVL 树接受泛型类型参数并将值存储在节点内,该值必须是可比较的。节点子类存储了左右子节点指针,以及节点的高度和平衡因子。可以使用树打印机接口将树显示在终端上,代码中提供了size、isempty、setcontains等公共方法。还使用基本案例和比较值来解释插入方法,以确定插入是否成功。
- 07:20:00 解释了AVL树中的私有插入方法,该方法将新节点插入到左子树或右子树中,同时相应地更新节点的平衡因子和高度。 update方法更新节点的高度和平衡因子,balance方法调用必要的旋转方法来维持树的平衡。解释了左-左、左-右、右-右和右-左情况,并强调旋转后更新方法的顺序对于AVL树保持平衡至关重要。
- 07:25:00 讲师讨论二叉搜索树数据结构的删除方法。他解释说,要删除一个元素,该方法首先检查该元素是否存在于树中,然后调用私有删除方法。讲师概述了删除过程中可能出现的四种情况,并提出了一种启发式方法来确定在尝试删除具有两个子树的节点时从哪个子树中删除。最后,他提醒观众在删除方法的回调中调用更新和重新平衡方法,以确保尽管节点被删除,树仍然保持平衡。
- 07:30:00 Google工程师介绍了索引优先级队列,这是一种支持键值对快速更新和删除的数据结构。它解决了能够快速查找和动态更改优先级队列中的值的问题,这在各种情况下都很有用,例如医院候诊室,患者需要首先得到最高优先级的服务。工程师提供了具有不同优先级的患者的示例,以及索引优先级队列如何帮助动态更新优先级。
- 07:35:00 该视频讨论了索引优先级队列,它允许对某些项目的优先级进行有效的动态更新。使用索引优先级队列的第一步是将索引值分配给所有键,创建双向映射。这种映射应该是双向的,并且可以通过双向哈希表来促进。在键上使用索引值的原因是为了能够对数组进行索引,这通常是优先级队列的实现方式。
- 07:40:00 演讲者介绍了索引优先级队列的概念,并解释了它应该支持的操作,包括删除键、获取与键关联的值、检查优先级队列中是否存在键、获取键索引最小值,获取索引中的最小值,能够插入和更新键值对,专门的更新操作增加和减少键。所有这些操作的时间复杂度要么是常数,要么是对数。演讲者还回顾了传统优先级队列数据结构,包括二叉堆如何工作、如何向优先级队列插入新值以及如何从优先级队列中删除项目。
- 07:45:00 我们如何用二叉堆实现索引优先级队列?第一步是为每个项目分配一个唯一的索引值和索引优先级队列的初始值。然后,我们使用最小索引优先级队列首先按最低值排序,并维护一个位置图来告诉我们任何给定键索引的堆中节点的索引。此外,我们维护一个反向查找表来查找给定节点的键。这些信息使我们能够有效地访问和操作各种应用程序的优先级队列,例如优先考虑医院中的患者或餐厅中的顾客。
- 07:50:00 该视频讨论了如何执行有用的操作,例如在索引优先级队列中插入、更新和删除键值对。插入过程与常规优先级队列类似,但增加了更新位置和逆映射的步骤。该视频提供了插入过程的伪代码,展示了节点如何在堆中向上移动,直到满足堆不变量。交换过程涉及更新位置和逆映射,但不更新值数组,该数组仍然由键索引而不是节点索引进行索引。该视频还简要介绍了轮询和删除键值对,这涉及与插入类似的步骤,但步骤相反。
- 07:55:00 该视频解释了如何利用现在为常数时间的节点位置查找,将从索引优先级队列中删除元素的时间复杂度从线性时间复杂度改进为对数时间复杂度。该视频提供了如何删除节点的分步示例,包括交换节点、在删除之前存储键值对、清理删除的节点以及通过向上或向下移动交换的节点来恢复堆不变量。此外,还提供了用于删除键值对的伪代码,展示了简短的五行实现和三行清理过程。最后,视频介绍了sync方法及其工作原理,以及键值对更新,与remove类似,但也需要对数时间。
- 2019.09.19
- www.youtube.com
C 编程完整课程免费
00:00:00 - 01:00:00 “C 编程免费完整课程”视频教观众如何安装 gcc 编译器、设置 IDE 以及编写 C 代码。该视频涵盖了 C 编程的基础知识,包括如何使用 printf 语句、注释、转义序列和格式说明符来显示不同的数据类型。讲师解释如何创建和初始化变量,以及如何使用算术和递增/递减运算符。此外,该视频还介绍了使用 scanf 接受用户输入以及使用 printf 格式化输出。讲师还讨论了 C 语言中有用的数学函数,以及如何使用它们根据用户输入的半径来计算圆的周长和面积。视频强调,虽然C是一门很难的语言,但任何人都可以通过坚持和努力来学习它。
01:00:00 - 02:00:00 “C 编程免费完整课程”YouTube 视频教授 C 语言编程概念。在本视频部分中,讲师介绍了 if/else 语句、switch 语句、逻辑运算符、函数和循环等主题。讲师解释条件语句,允许程序根据条件做出选择,以及 switch 语句如何成为 else if 语句的更有效版本。此外,讲师还深入展示了如何转换温度单位、创建简单的计算器程序、使用逻辑运算符来提高程序效率,以及如何使用函数来最大限度地减少代码冗余。最后,讲师解释了三元运算符以及字符串函数如何帮助程序创建。
02:00:00 - 03:00:00 这门 C 编程完整课程涵盖了广泛的主题,首先解释 while 和 do-while 循环之间的区别,以及如何使用嵌套循环创建形状。然后,该视频将介绍数组的基础知识以及如何循环和显示一维数组中的元素,然后再介绍二维数组以及如何创建二维网格或数据表。然后,讲师介绍交换变量的概念、冒泡排序等排序算法,并教授 C 语言中的结构体和 typedef,以及生成随机数和制作猜数字游戏。总的来说,本课程提供了对 C 编程概念的全面和深入的理解。
03:00:00 - 04:00:00 这个名为“免费 C 编程完整课程”的 YouTube 视频涵盖了全面的 C 编程主题,包括创建猜数字和问答游戏等游戏,并涵盖了诸如内存、指针、按位运算符和文件 I/O。此外,该视频还介绍了如何创建井字棋游戏,该游戏使用嵌套的 for 循环和 if 语句来检查获胜者并为计算机玩家生成随机移动。讲师在整个视频中提供了清晰的解释和演示,使其成为任何有兴趣学习 C 编程的人的宝贵资源。
04:00:00 - 04:00:00 讲师继续用 C 语言构建 Tic-Tac-Toe 游戏,在下棋之前添加检查以确保所选位置为空,并创建一个函数来打印获胜者。然后,他们使用 do while 循环添加“再次播放”选项,并在每个循环开始时重置变量。代码将在评论区分享,供用户使用。
第1部分
- 00:00:00 作者阐述了学习C的重要性,C是一种中级语言,充当高级软件和低级硬件之间的桥梁。 C 起源于 20 世纪 70 年代,广泛用于各种用途,包括编写编译器、操作系统和数据库。 YouTuber 还提供了有关如何设置 IDE 以及安装必要的扩展和编译器以开始编写 C 代码的说明。然而,YouTuber 警告说,C 对于初学者来说是一门困难的语言,但只要坚持和努力,任何人都可以学会它。
- 00:05:00 该视频介绍了如何在 Mac 或 Linux 系统上安装 gcc 以及如何在环境变量下添加 gcc 编译器的路径。安装 gcc 后,视频将继续解释如何配置默认构建任务,以便 VS Code 知道如何编译程序。该视频建议增加字体大小并启用自动保存,以免日后出现麻烦。该视频还介绍了 C 编程的基础知识,并包括重要的函数,例如主题标签 include、标准 io 输入/输出的 std 以及打印 f 括号。最后,视频强调需要在主函数末尾添加 return 0 语句以检查是否有任何错误。
- 00:10:00 在 C 编程教程的这一部分中,讲师演示如何使用 printf 语句打印文本以及如何使用转义序列添加新行字符。他还演示了如何使用命令提示符编译和运行 C 文件,并解释了 C 编程中注释的用途。该视频涵盖了 C 语言编程的基础知识,并为初学者提供了有用的提示。
- 00:15:00 在 C 编程视频教程的这一部分中,讲师解释了如何在代码中使用注释和转义序列。注释用于为任何阅读代码的人提供解释、描述或注释。单行注释是使用两个正斜杠进行的,而多行注释是使用正斜杠后跟一个星号进行的,并以星号后跟一个正斜杠结尾。另一方面,转义序列是指定一行文本或字符串内操作的字符组合。最常用的转义序列用于在文本字符串中创建新行和制表符。讲师还演示了如何使用转义序列显示引号、单引号和反斜杠。
- 00:20:00 视频讨论了如何在 C 编程中创建变量。首先,您必须声明一个变量并为该变量分配名称和数据类型。接下来,您必须通过将其设置为等于某个值来初始化该变量。该视频提供了不同数据类型的示例,包括整数、浮点、字符和数组。该视频还解释了如何使用 printf 语句和格式说明符显示变量中存储的值。
- 00:25:00 在视频的这一部分中,讲师解释了如何使用格式说明符在 C 编程中显示不同的数据类型。例如,要显示字符数组,请使用百分号后跟“s”作为字符串。要显示字符变量,请使用百分号 c,要显示浮点数,请使用百分号 f。讲师还讨论了字符、浮点数、整数和双精度数等数据类型,其中双精度数具有 64 位精度,并且比浮点数保留更多有效数字。还引入了布尔值,存储 true 或 false 并使用一个字节的内存。下一个视频将讨论不同的格式说明符以及自定义它们的方法。
- 00:30:00 我们了解到布尔值可以使用百分比 d 显示,其中 1 表示 true,0 表示 false。字符可以存储负 128 到正 127 范围内的整数,其表示形式使用百分比 d 或百分比 c 格式说明符显示。无符号变量将字符和 Shorts 的正数范围加倍,因此 char 可以存储 0 到 255 之间的数字,而 Shorts 可以存储从负 32,768 到正 32,767(如果有符号)的数字,如果无符号则可以存储从 0 到 65,535 的数字。我们了解到您可以使用short 而不是short int 作为简写。整数可以存储正值或负值的整数。
- 00:35:00 需要注意的是,不同的数据类型有不同的格式说明符,使用错误的格式说明符可能会导致错误或意外的输出。虽然 C 编程中有许多可用的数据类型,但在本课程中我们将主要关注字符、字符数组、双精度数、布尔值和整数。
- 00:40:00 讲师解释格式说明符,格式说明符定义并格式化要以指定方式显示的数据类型。要设置显示输出的最小字段宽度,请在百分号后添加一个数字以分配特定空间。在百分号后使用负号可将数据左对齐。该视频还介绍了常量,这些常量是程序在执行过程中无法更改的固定值。要将变量转换为常量,数据类型前面要加上关键字“const”,并遵循大写约定来命名常量。还涵盖了加、减、乘、除等算术运算符,其中整数除法可以截去小数部分,需要使用 float 或 double 来存储结果,模运算符用于获取任何除法的余数。
- 00:45:00 讲师解释了 C 编程中的算术运算符,包括模数,模数可用于通过求除以 2 时的余数来快速确定数字是偶数还是奇数。视频还介绍了增量和减量运算符,这些运算符可用于将变量增加或减少 1,以及增强赋值运算符,允许用户对变量执行算术运算并使用快捷方式将结果赋回同一变量。最后,讲师概述了如何在 C 编程中使用 scanf 函数和提示接受用户输入。
- 00:50:00 讲师解释了如何使用 scanf 函数以及针对所使用变量类型的适当格式说明符在 C 编程中接受用户输入。本节介绍了接受整数和字符串,但需要注意的是,由于存在空格,接受带有空格的字符串需要 fgets 函数而不是 scanf 。讲师还解释了如何在使用 fgets 去除换行符后格式化字符串。本节最后概述了 printf 语句格式以提高可读性。
- 00:55:00 在视频的这一部分中,讲师讨论了 C 中包含数学头文件时有用的数学函数。平方根、幂、舍入(使用上限和下限)、绝对值、对数和三角函数通过如何在代码中使用它们的示例进行了解释。随后,讲师演示了如何编写一个程序,根据用户输入的半径来计算圆的周长,并进一步使用 pi 乘以半径平方公式来计算和显示圆的面积。
第2部分
- 01:00:00 在这一部分视频中,讲师演示了如何使用C编程语言计算圆的周长和面积,以及如何找到直角三角形的斜边,这需要使用平方根函数来自 math.h 头文件。讲师还介绍了 if 语句以及如何使用它们通过检查条件并相应地执行代码来向程序添加选择。他演示了如何使用大于或等于条件和双等号比较运算符,以及如何使用 else 语句在条件为假时提供不同的输出。
- 01:05:00 该视频讨论了 C 编程中的 if 语句和 else if 语句。这些语句允许程序检查条件是否为真,如果是则执行特定的代码子集,如果不是,程序将向下移动到下一个块以检查另一个条件。如果所有条件都为 false,则程序将执行 else 块中的代码。此外,该视频还介绍了 switch 语句的使用,作为使用多个 else if 语句的更有效的替代方案。 switch 语句允许使用 case 关键字针对多种情况测试值的相等性。最后,该视频强调了在 switch 语句中的每个 case 后面添加 break 语句的重要性,以便在找到匹配的 case 后退出 switch。
- 01:10:00 在视频的这一部分中,讲师教授如何创建一个程序,将温度从摄氏温度转换为华氏温度,反之亦然。该程序接受用户输入的测量单位(摄氏度或华氏度)和当前温度,然后使用 if/else 语句和适当的公式来执行转换。讲师还演示了如何使用 to_upper 函数来处理区分大小写以及如何使用 scanf 接受浮点数。程序提示用户输入并显示转换后的温度。
- 01:15:00 在课程的这一部分中,讲师演示如何使用 C 创建一个程序,根据用户输入转换温度单位(摄氏度到华氏度,反之亦然)。该程序提示用户输入温度和测量单位,使用 scanf 接受输入,然后使用一系列条件语句根据需要转换温度单位。讲师解释了如何使用格式说明符、摄氏度到华氏度的转换公式以及 switch 语句来处理程序流程中不同类型的操作。最终程序发布在评论部分供下载和审核。
- 01:20:00 在视频的这一部分中,讲师演示了如何用 C 创建一个简单的计算器程序,可以执行加法、减法、乘法和除法。程序使用 switch 语句根据用户的输入确定执行哪个操作。此外,还解释了逻辑运算符的使用,特别是“and”运算符,它检查一组条件是否为真。讲师提供了如何使用逻辑运算符检查温度是否在特定范围内以及如何在条件检查中包含布尔变量的示例。
- 01:25:00 讨论 or 逻辑运算符和 not 逻辑运算符。 or 逻辑运算符检查至少一个条件是否为真,而 not 逻辑运算符则反转条件的状态。 or 运算符可用于通过添加更多竖线来检查多个条件。另一方面,not 运算符可以为程序的编写方式提供更多选择。这些逻辑运算符可以帮助创建更复杂的条件并提高程序的效率。
- 01:30:00 讲师教授如何在 C 编程中使用函数以避免重复相同的代码。通过创建新函数,只需编写一次代码,然后只需调用该函数即可多次重复使用代码。然后,讲师继续讨论参数和参数,并举例说明将字符数组和整数作为参数传递给函数。需要在函数声明中声明参数,以使函数知道传递给它的变量。如果没有匹配的参数集,则无法调用该函数。
- 01:35:00 在这一部分的文字记录中,演讲者解释了 return 语句的概念以及它如何将值返回给调用函数。他们演示了一个名为“square”的函数示例,该函数将接受一个参数,对该参数求平方,然后将结果返回给调用函数。他们还讨论了三元运算符的语法,这是分配或返回值时使用 if-else 语句的快捷方式,并展示了如何使用它来查找两个整数中的最大值的示例。演讲者还强调了在函数声明中使用 return 关键字时匹配数据类型的重要性。
- 01:40:00 我们了解三元运算符,它是在赋值或返回值时使用 if-else 语句的快捷方式。该运算符由一个条件、后跟一个问号、条件为 true 时返回的值、冒号以及条件为 false 时返回的值组成。我们还讨论了函数原型,它确保使用正确数量和类型的参数来调用函数。通过在主函数之前添加函数原型,我们可以避免意外行为,并在使用不正确的参数时收到错误。
- 01:45:00 在视频的这一部分中,讲师解释了 C 语言的函数原型及其优点,并介绍了一些已经用 C 语言编写的有用的字符串函数,例如字符串长度、字符串比较、字符串下限、字符串上部和串猫。讲师举例说明了每个函数的工作原理并演示了它们的输出。如果要比较的两个字符串相同,则字符串比较函数返回零,如果不同,则返回其他数字。讲师通过添加使用这些字符串函数的代码片段来结束本节。
- 01:50:00 讲师介绍 for 循环,它重复一段代码有限的次数。他提供了一个使用 for 循环从 1 计数到 10 的示例,并解释了 for 循环所需的三个语句:声明索引、定义重复代码多长时间的条件以及递增或递减索引的方法。他还演示了递增和递减索引的不同方法。然后,讲师继续解释 while 循环,只要某个条件保持为真,该循环就可能无限次地重复一段代码,并给出了一个提示用户输入姓名直到用户输入有效响应的示例。
- 01:55:00 在视频的这一部分中,讲师演示了如何在 C 编程中使用 fgets 而不是 scanf 进行用户输入。然后,他们使用 while 循环提示用户输入他们的名字,如果他们没有正确输入他们的名字,他们就会对他们大喊大叫。然后,讲师转而讨论 do-while 循环,并提供一个程序演示,该程序要求用户输入任意数量的数字(前提是这些数字大于零),并计算这些数字的总和。
第三部分
- 02:00:00 在 C 编程完整课程的这一部分中,讲师解释了 C 中 while 循环和 do-while 循环之间的区别。While 循环首先检查条件,然后如果条件满足则执行代码true,do-while 循环执行代码一次,然后在继续之前检查条件是否为 true。讲师通过示例代码对此进行了演示,并解释了如何将 while 循环修改为 do-while 循环。本节还介绍了嵌套循环(即另一个循环内的一个循环),并演示了使用嵌套循环根据行、列和符号的用户输入值打印符号矩形的示例。
- 02:05:00 在视频的这一部分中,讲师演示了如何使用 C 中的嵌套循环创建矩形形状。他允许用户输入矩形的符号以及行数和列数,但他还演示了如何清除输入缓冲区以允许正确的用户输入。讲师还解释了 C 循环上下文中的 continue 和 break 语句之间的区别,其中 continue 将跳过代码段的其余部分并强制进行循环的下一次迭代,而 break 将完全退出循环。最后,讲师将数组的概念定义为一种可以存储相同数据类型的许多值的数据结构,并演示如何将变量转换为数组。
- 02:10:00 该视频介绍了 C 编程语言中数组的概念。数组是一种在固定大小的数据结构中存储相同数据类型的多个值的方法。该视频演示了如何初始化数组并使用索引号访问特定元素。初始化数组的方法有多种,例如立即赋值或稍后在程序中赋值。该视频还解释了如何使用 for 循环循环并打印数组的所有元素。
- 02:15:00 该视频介绍了如何在 C 编程中循环并显示数组的元素。讲师演示如何使用 for 循环和 printf 语句,并使用 for 循环的索引来访问数组的元素。它们还展示了如何使用运算符的大小来计算循环应迭代的次数,如果从数组中添加或删除元素,它将自动更新。然后,讲师继续创建一个二维数组,该数组中的每个元素本身就是一个数组。他们使用简单的网格或数据表的示例演示了如何初始化和组织二维数组。
- 02:20:00 讲师介绍如何在 C 编程中声明二维数组并为其赋值。他们还解释了如何使用嵌套循环和格式说明符“d”显示二维数组的元素。然后,讲师演示如何使用运算符的大小和其中一行的大小,以及使用第一行中找到的一个元素的大小来计算二维数组的行数和列数。本节最后提供了一个示例,说明如何使用添加到二维数组的新行来测试代码。
- 02:25:00 在视频的这一部分中,讲师解释了如何在 C 中创建二维数组,这是一个数组的数组,其中每个元素都是一个完整的数组。两个索引用于访问其中一个元素 - 一个用于行,一个用于列。讲师还演示了如何创建字符串数组,该数组是单个字符的二维数组,但每个元素都是字符串。要显示字符串数组,可以使用 for 循环。最后,讲师通过引入第三个变量作为值的临时存储来解释如何在 C 中交换变量。交换变量在排序算法中很重要,这将在下一个主题中介绍。
- 02:30:00 讲师教授如何交换 C 中两个变量的值(整数和字符数组)。使用临时变量和字符串复制函数,讲师展示了如果第二个参数的长度小于第一个参数的长度,如何交换值并避免字符数组的意外行为。讲师还建议将变量想象成含有液体的玻璃杯,以更好地理解交换值,并在评论部分提供示例代码。接下来,讲师将解释如何编写程序对数组中的元素进行排序,首先使用整数数组,然后使用字符数组。讲师声明一个单独的排序函数,并使用嵌套的 for 循环来迭代数组并比较值以进行排序。
- 02:35:00 演讲者讨论如何使用冒泡排序算法对 C 中的数组元素进行排序。它们解释了临时变量和 if 语句的使用,以及正在排序的数字的大小如何影响其在数组中的最终位置。演讲者还演示了如何通过更改数据类型和打印函数对字符数组进行排序。然后,他们引入了结构的概念,作为在一个内存块中组织相关成员的一种方式,并具有模仿现实世界对象的能力。结构体是使用 struct 关键字定义的,后跟标签名称和一组代表其成员的花括号。
- 02:40:00 在视频的这一部分中,讲师教授 C 编程语言中的结构体和 typedef。结构允许程序员将相关值分组到内存块中的一个名称下,并且这些可用于将值分配给具有不同数据类型的成员。 typedef 关键字为现有数据类型提供昵称,这使得在代码中使用该数据类型变得更加容易。讲师还演示了创建具有三个成员的结构并向它们分配值的示例。该视频为想要使用它的用户提供了示例代码。
- 02:45:00 该结构是在主函数之外创建的,并指定了一个标签名称“student”,并包含一个用于名称的字符数组和一个用于 GPA 的浮点变量。初始化由四个学生组成的数组,然后将其放入名为“students”的数组中。使用 for 循环,程序循环遍历数组并使用点成员访问运算符打印出每个学生的姓名和 GPA。最后,视频解释说,如果我们对结构体使用“typedef”关键字,我们就不再需要使用 struct 关键字来创建结构体,而是可以使用我们分配给它的昵称。
- 02:50:00 讲师教授如何用 C 创建结构体数组,其中数组中的每个元素都是一个包含每个学生数据(例如姓名和 GPA)的结构体。讲师还介绍了枚举的使用,枚举是用户定义的命名整数标识符类型,可以通过用关联名称替换整数值来使程序更具可读性,从而使程序员和审查代码的任何人更容易理解代码。概述了枚举的结构,讲师演示了如何在 if-else 语句中使用枚举来根据枚举变量的值打印不同的输出。
- 02:55:00 在视频的这一部分中,讲师演示了如何在 C 编程中生成随机数。当前时间用于生成 rand 函数的种子,该函数生成 0 到 32767 之间的随机数。要获得给定范围内的随机数,可以使用模运算符。讲师提供了生成 1 到 6 之间的随机数(用于掷骰子)和掷三个骰子的示例。还引入了利用生成随机数的知识的猜数字游戏。设置最小和最大范围的常数,并提示用户猜测数字。该程序使用 rand 函数在给定范围内生成一个随机数,用户会收到反馈来调整他们的猜测,直到输入正确的数字。
第 4 部分
- 03:00:00 讲师教授如何用 C 语言创建一个猜数字游戏,程序会生成两个指定值之间的随机数,提示用户猜测数字,并在猜测过高或过低时提供反馈,或者正确。该程序使用 do-while 循环来确保至少进行一次猜测,并计算用户猜测的次数。讲师还添加了一些文本装饰,使输出更具视觉吸引力。此示例演示了 C 中条件语句、循环、用户输入和随机数生成的使用。
- 03:05:00 讲师演示如何用 C 语言创建问答游戏。该游戏使用二维字符数组来存储问题,并使用单独的二维字符数组来存储选项。正确答案存储在一维字符数组中。游戏会计算问题的数量,并使用 for 循环逐一循环,显示它们及其可能的选项。为此,讲师使用嵌套 for 循环,该循环从选项数组中的每四个字符串开始。这个 for 循环循环四次,显示每个问题的四个可能选项。
- 03:10:00 讲师演示如何用 C 语言创建一个简单的问答游戏,提示用户提出问题并检查他们的答案。该代码使用嵌套的 for 循环来显示问题和选项,使用 scanf 接受用户输入,并使用“toupper”函数将小写字符转换为大写字符。然后,程序检查用户的猜测是否与正确答案匹配,并相应地增加分数。回答完所有问题后,程序将显示最终分数。讲师还简要解释了按位运算符,并演示了如何在 C 中使用五种不同的按位运算符。
- 03:15:00 我们学习 C 编程中的按位运算。我们从 AND 运算符开始,当应用于两个二进制数时,仅当两个对应位都为 1 时,才会将 1 分配给我们的结果。然后,我们继续使用 OR 运算符,如果任何相应位为 1,则该运算符将把 1 分配给我们的结果。如果只有一个对应位为 1,则异或运算符会将结果分配为 1。我们还了解左移和右移运算符,它们将二进制数中的位向左或向右移动。将位向左移动可以有效地使数字加倍,而向右移动则会产生相反的效果。
- 03:20:00 该视频解释了 C 编程中的内存,它是 RAM 中的字节数组,每个单元都是可以保存一个值的内存块。内存地址指向内存块在 RAM 中的位置,就像街道地址一样。声明变量时,它会留出一些内存块来保存与内存地址关联的值。每个变量使用一个字节的内存块,视频中显示了内存地址和各种字符的大小作为示例。该视频还简要解释了十六进制值,它使用 0 到 9 的数字和 a 到 f 的字母为每个数字创建 16 个可能的值。最后,视频介绍了使用两个字节内存的短数据类型。
- 03:25:00 讲师解释了 C 编程中的内存基础知识,包括变量如何使用内存块以及数组如何根据其大小和数据类型使用多个内存块。他还介绍了指针的概念,指针将内存地址作为另一个变量的值,并解释了如何使用它们更轻松地执行某些任务。讲师演示如何显示变量的值和地址,以及如何创建与其指向的变量具有相同数据类型的指针。
- 03:30:00 我们学习 C 编程中的指针。指针使用星号作为间接运算符来声明,常见的命名约定是使用小写“p”,后跟第一个字母大写的变量名。指针的值是一个地址,我们可以使用间接运算符访问存储在该地址的值。确保指针和它指向的变量的数据类型一致非常重要。指针还可以作为参数传递给函数,允许函数访问和修改存储在指向变量中的值。此外,指针可以通过两个步骤来声明和初始化,但立即赋值是一种很好的做法。
- 03:35:00 讲师讲解 C 编程中的指针。指针是一个变量,它保存另一个变量、数组等的内存地址。要声明指针,可以使用间接运算符。要将值分配给指针,可以使用相同的运算符。讲师演示如何使用指针、fopen、fwrite 和 fclose 在 C 中写入文件。要写入文件,您需要创建一个指向文件的指针并使用“fprintf”写入文件。讲师还通过删除文件和写入计算机目录上特定位置的文件来演示文件 I/O。
- 03:40:00 讲师演示如何在 C 编程中通过创建数据类型为“file”的指针并使用 fopen 函数打开文件来读取文件的内容。讲师演示如何使用缓冲区来包含字符数组以一次保存文本文档的一行,以及如何使用 fgets 函数从文件中读取一行。本节还包括如何使用 while 循环显示文件中的所有行以及如何添加文件检测以在尝试读取文件之前检查文件是否存在。
- 03:45:00 在视频的这一部分中,讲师将介绍程序中将使用的功能原型,包括重置棋盘、打印棋盘、检查可用空间、玩家移动、计算机移动、检查获胜者的功能,并打印获胜者。声明这些函数后,讲师讨论一些要使用的全局变量,包括名为 board 的二维字符数组,以及玩家和计算机字符的常量。接下来讨论主函数,它为获胜者声明一个局部变量,将其设置为空白,重置棋盘并打印它。该视频还详细介绍了重置板函数中使用的嵌套 for 循环以及打印板中使用的 printf 语句。
- 03:50:00 在 C 编程完整课程的这一部分中,讲师解释了如何在主函数中创建围绕打印板函数的 while 循环。 while循环的条件是,如果获胜者是一个空空间,并且调用检查空闲空间函数的返回值不等于0,则循环将继续。检查可用空间函数也是使用两个嵌套的 for 循环创建的,以循环遍历字符的二维数组,并在任何位置被占用时减少可用空间局部变量。解释玩家移动功能,提示用户输入行号和列号进行移动,并检查位置是否被占用。还创建了检查获胜者函数来检查每一行是否有获胜条件以及检查每一列是否有获胜条件。
- 03:55:00 讲师复习了在 Tic Tac Toe 游戏中检查行、列和对角线以确定获胜者的代码。他们解释了如何使用 for 循环和 if 语句来迭代游戏板中的元素并检查匹配项。如果有获胜者,该函数将返回获胜元素的字符值。如果不是,则返回空字符。然后,教练提供计算机移动的代码,其中涉及生成随机坐标以将其符号放置在棋盘上。在生成随机数之前,程序会检查棋盘上是否有可用空间。
- 04:00:00 讲师继续用 C 语言构建 Tic Tac Toe 游戏。他们添加了一项检查,以确保在移动之前生成的位置是空的。如果没有更多可用空间,则使用空空间调用“打印获胜者”功能,这意味着游戏是平局。他们解释说,这个函数相当简单,因为如果获胜者是玩家,它会打印“你赢了”;如果获胜者是计算机,它会打印“你输了”;如果没有赢家,它会打印“平局”。讲师使用 do while 循环实现“再次玩”选项,并在每个循环开始时重置获胜者和响应变量。该游戏经过多次运行和测试,教练会解释每个步骤。最后,他们提到代码将发布在评论部分供用户使用。
- 2021.10.07
- www.youtube.com
面向对象编程的基本概念
面向对象编程的四个基本概念是抽象、封装、继承和多态。在深入研究它们的含义之前,了解对象是什么很重要。对象代表现实世界中的某些东西,它可以是物理的,如汽车或一本书,也可以是非物理的,如牙科预约或银行账户。
在面向对象编程的上下文中,对象是指正在开发的软件应用程序感兴趣的任何事物,其中需要存储和处理数据。对象也称为实体。
抽象是第一个基本概念,它涉及通过仅关注与对象相关的相关数据和任务来简化现实。例如,在设计处理有关人员的数据的应用程序时,仅考虑必要的数据和操作。
要以编程方式创建对象,需要一个类。类充当创建对象的模板,由程序员编写,用于定义对象的属性(也称为字段或属性)和操作(也称为行为或方法)。属性描述对象的数据,而操作表示对象可以执行的操作。
封装是第二个基本概念,涉及向其他程序和程序员隐藏对象内部工作的复杂性。它通常被称为信息隐藏,因为对象内的数据和功能被绑定在一起并免受外部干扰。有经验的程序员经常创建初级程序员使用的类,并且编译的类库可以保护知识产权。
继承是第三个基本概念,允许一个类从另一个类派生其方法和属性。这导致了类的层次结构,其中子类继承自超类。例如,员工类继承自人员类,客户类也继承自人员类。这创建了一种关系,子类扩展其超类的属性和方法。
多态性是最后一个基本概念,它使类能够以自己的方式实现继承的方法。同一超类的不同子类可以对继承的方法有不同的实现。多态性允许具有相同接口的不同形式的对象有不同的行为,具体取决于它们特定的子类实现。
总而言之,抽象简化了现实,封装隐藏了复杂性,继承建立了类层次结构,多态性允许继承方法的多种实现。这些基本概念构成了面向对象编程的基础。
- 2020.11.01
- www.youtube.com
C++ 中的面向对象编程 (OOP) 课程
该视频概述了 C++ 中的面向对象编程 (OOP)。它解释了 OOP 的基本概念,例如类、对象和方法。讲师演示了 C++ 类及其成员的创建,强调将变量声明为用户定义数据类型的重要性。访问修饰符(如 private、public 和 protected)是与访问对象成员相关的。
该视频还涵盖了 OOP 原则的实现,包括封装、抽象、继承和多态性。它展示了如何在代码中应用这些原则的示例,例如创建构造函数和抽象类。讲师强调了 OOP 的优点,例如简化软件开发并向用户隐藏复杂性。
此外,该视频还探讨了继承的概念,即派生类从基类继承属性。讲师演示了创建派生类的过程,并解释了除了继承的属性之外,派生类如何拥有自己独特的属性。
视频最后讨论了虚拟函数和多态性。它解释了多态性如何允许对象和方法具有多种形式,从而使父类引用能够与子类对象一起使用。引入了虚函数的概念,强调函数的最派生版本在调用时被执行。
总的来说,该视频旨在提供对 C++ 中的 OOP 的全面理解,涵盖基本概念、原则和实际实现。该讲师鼓励观众关注她的频道 Code Beauty,并欢迎对视频提出反馈。
- 00:00:00 该视频介绍了面向对象编程的基础知识及其在实践中的工作原理。类是面向对象编程中的关键概念,变量必须声明为用户定义的数据类型才能使用它们。
- 00:05:00 在此视频中,创建了一个 C++ 类并添加了成员。该类具有三个属性:姓名、公司和年龄。创建该类的实例并为其分配变量号。
- 00:10:00 在此视频中,讲师解释了如何在 C++ 中访问对象的成员。访问修饰符(例如 private、public 和 protected)决定如何访问对象的成员。类方法可用于描述对象的行为。
- 00:15:00 该视频解释了面向对象编程 (OOP) 如何在 C++ 中工作。创建一个返回类型为 void 的函数,并使用与引入的函数相同的语法来调用该函数。然后调用该函数五次,每次使用不同的员工姓名和公司。然后,将员工姓名和公司值复制到新的员工对象,并将员工对象的属性设置为新复制的值。
- 00:20:00 在此视频中,讲师介绍了在 C++ 中创建构造函数的三个规则。第一条规则是构造函数与其所属的类具有相同的名称,第二条规则是构造函数必须是公共的,第三条规则是构造函数必须可访问。创建构造函数时,请务必记住本视频中概述的规则。如果构造函数不遵循这些规则之一,就会生成错误。
- 00:25:00 在本视频中,讲师解释了面向对象编程的基础知识,包括类、对象和方法的概念。然后,他继续描述面向对象编程的四个关键原则:封装、抽象、继承和多态性。最后,他解释了如何在代码示例中实现这些概念。
- 00:30:00 该视频介绍了 C++ 中的面向对象编程 (OOP)。类是封装数据和公共方法的结构,其他类可以调用这些方法来访问和修改数据。为了提供封装,类字段是私有的,而 getter 和 setter 是公共的。
- 00:35:00 在此视频中,C++ 课程讲师讨论了面向对象编程 (OOP) 的原理。讲师讨论封装和抽象如何帮助将复杂的数据隐藏在简化的界面后面。讲师还讨论了如何将验证规则应用于私有属性的 setter 方法。
- 00:40:00 在此视频中,演示者解释了面向对象编程 (OOP) 如何通过向用户隐藏复杂性来简化软件开发。他们使用智能手机的示例来说明 OOP 如何使复杂的过程看起来简单。然后,他们演示如何创建一个合约,使系统的一侧看起来很简单,同时向用户隐藏系统的复杂性。
- 00:45:00 该视频解释了 C++ 中的面向对象编程 (OOP) 概念。该视频讨论了如何创建需要实现虚拟函数的抽象类,以及如何测试该函数以查看特定员工是否可以获得晋升。
- 00:50:00 在此视频中,作者获得晋升,如果该人年龄小于 30 岁,则该人不会获得晋升。这允许我们实现一个合约,它实际上是一个抽象类,并且该抽象类或该合约只有一个规则,该规则就是这里的纯虚函数,称为“要求提升”。因此,无论哪个类签署了这个合同,无论哪个类继承了这个抽象员工,也就是这里的这个类,都必须在这里提供这个方法的实现。我们测试了它,正如你所看到的,我没有得到晋升,而约翰却得到了晋升,这就是抽象的想法。这个要求促销的方法就是我们在本章开头提到的智能手机上的按钮。我想讲的面向对象编程的第三个原则叫做继承。继承的思想如下:有一个基类,也称为超类或父类,然后有派生类,也称为子类或子类。
- 00:55:00 在此视频中,C++ 课程讲师通过从现有基类创建派生类来演示面向对象编程的工作原理。然后,派生类继承基类属性,派生类还获得其自己特定于开发人员类的属性。
- 01:00:00 在本视频中,讲师讨论了 C++ 中面向对象编程的工作原理。他解释了开发人员类如何从雇员类继承,以及如何使用雇员类的构造函数来初始化开发人员类的某些属性。然后,讲师演示如何在开发人员类上创建方法来测试属性是否已正确设置。最后,他演示了如何关闭开发者类。
- 01:05:00 在此视频中,讲师讨论继承和多态性的面向对象编程 (OOP) 概念。他通过代码示例演示了如何使用这些概念来解决问题。最后,讲师演示了如何创建一个继承于另一个类的类。
- 01:10:00 该视频简要概述了 C++ 中的面向对象编程 (OOP)。该视频介绍了如何创建一个继承于员工类的教师类并实现备课功能。该视频还讨论了创建和使用 OOP 类时可能出现的一些问题以及如何解决这些问题。
- 01:15:00 在此视频中,讲师解释了 C++ 中面向对象编程 (OOP) 的概念。多态性是指对象或方法具有多种形式的能力。编程中多态性的一种常见用途是使用父类引用来引用子类的对象。此示例通过返回主函数并在开发人员类和教师类(均继承自雇员类)上调用新工作方法来演示多态性的工作原理。
- 01:20:00 该视频介绍了 C++ 中面向对象编程的基础知识。视频的第一部分介绍了面向对象编程的历史以及它与其他编程范例的不同之处。视频的第二部分解释了如何创建指向基类的指针,以及如何在员工类中创建虚拟工作方法。最后,视频演示了指针如何工作以及程序如何工作。
- 01:25:00 在本视频中,讲师讨论了 C++ 中的虚函数和多态性的概念。他解释说,当调用虚拟函数时,将执行该函数的最派生版本。这意味着,如果某个函数未在类的派生类中实现,则将调用该类的开发人员类。他还指出,通过多态性,可以将不同类型的员工视为一个大对象,从而允许使用基类指针来引用它们。
- 01:30:00 该视频介绍了 C++ 中的面向对象编程 (OOP)。它讨论了 OOP 如何使编程更有条理、更容易理解。主讲者还建议观众关注她的频道、代码之美,并在那里订阅。最后,主持人鼓励观众对她的视频留下反馈。
- 2021.02.02
- www.youtube.com
在我们技术先进的世界中,编程和计算机科学已成为推动创新和塑造社会的变革性学科。
编程作为一种艺术形式,结合了创造力、逻辑和解决问题的能力,创造出优雅而高效的解决方案。
计算机科学是编程的科学基础,涵盖计算机程序开发和实现的理论、算法和方法。然而,编程本身需要想象力和独创性。就像空白画布艺术家一样,程序员将一行行代码编织成复杂的算法,创造出能够彻底改变行业、简化任务并增强用户体验的数字杰作。面向对象编程(OOP)是计算机科学中的一个关键范例,它允许程序员通过将代码组织成可重用和模块化的对象来管理复杂性。通过将数据和行为封装在对象中,程序员可以创造性地设计更易于理解、维护和扩展的解决方案。
编程不仅仅是解决问题,还包括设计用户友好的界面和引人入胜的用户体验。这方面将艺术敏感性与技术知识结合起来。程序员利用美观、直观的导航和引人注目的视觉效果来设计用户界面 (UI) 和用户体验 (UX),以创建令用户满意和着迷的软件。艺术在于将功能与审美吸引力无缝融合,将复杂的功能转化为直观且视觉上令人愉悦的设计。通过 OOP,程序员可以分离任务并创建负责软件不同方面的单独对象。这种模块化方法允许程序员专注于单个对象、它们的交互以及系统的整体行为,从而提高了设计的创造力。使用继承和多态性等面向对象编程原则,程序员可以开发出具有直观界面、用户友好界面和视觉上吸引人的美感的软件。
软件工程是计算机科学的一门学科,强调编程的艺术性。它涵盖了整个软件开发生命周期,从需求收集到部署和维护。软件工程师像建筑师一样进行编程,设计可靠、可扩展和可维护的系统和平台。他们考虑代码模块化、可重用性和架构模式等因素来创建兼具功能性和优雅性的软件解决方案。软件开发的艺术是平衡技术约束、用户需求和设计目标,以创建既实用又美观的软件。 OOP 通过提供结构化方法来管理复杂性,在软件开发中发挥着关键作用。将代码分为类和对象使软件开发人员能够设计模块化、可重用和可维护的系统。通过正确的抽象和封装,软件开发人员可以取得平衡,从而开发出既实用又优雅的软件。
编程艺术和计算机科学超越了技术领域,影响着整个行业和社会。从医疗保健到金融,从教育到娱乐,编程和计算机科学正在彻底改变我们的工作、沟通和生活方式。人工智能、虚拟现实和区块链技术等创新正在改变行业,开辟新视野。程序员和计算机科学家在这些变革性进步中发挥着关键作用,突破了可能的界限,将想法变为现实。 OOP 允许程序员创建彻底改变各个领域的创新解决方案。通过利用 OOP 的模块化和可扩展性来管理复杂性,程序员可以开发复杂的系统,例如人工智能算法、沉浸式虚拟现实体验和安全的区块链应用程序。这些进步正在改变行业、提高生产力并改善世界各地人们的生活质量。
复杂性管理是软件开发的一个关键方面。随着系统变得越来越复杂,有必要使用有效的方法来管理复杂性并确保可维护性和可扩展性。
面向对象范式是一种强大的方法,在管理复杂性方面具有显着的优势。通过将数据和行为封装在对象中,并使用封装、继承和多态性等概念,面向对象范式为管理复杂性提供了坚实的基础。
封装是面向对象范式的基本原则,它促进对象内数据和方法的关联。这种封装隐藏了对象的内部复杂性,仅公开与其交互所需的接口。通过隐藏实现细节,封装降低了系统其他部分的复杂性,使开发人员能够专注于更高级别的抽象。这促进了模块化并提高了代码可读性,使复杂的系统更易于理解和维护。
抽象是面向对象范式中帮助管理复杂性的另一个关键概念。这使得开发人员能够将复杂的现实世界对象表示为类,从而抽象出不必要的细节。通过创建抽象类和接口,开发人员可以定义可由多个子类继承和实现的通用行为和属性。这种类的分层组织允许开发人员通过将复杂的系统分解为更小、更易于管理的组件来管理复杂性。每个类都专注于其特定的职责,从而产生更加模块化和易于理解的代码库。
继承是面向对象范式提供的强大机制,可以促进代码重用并减少冗余。这允许新类通过在现有类之间建立“是”关系来继承现有类的属性和行为。继承允许开发人员定义具有公共属性和行为的基类,然后创建从其继承的专用类,从而有助于管理复杂性。这种类的层次结构消除了代码重复、降低了复杂性并提高了可维护性。
多态性是面向对象范例的一个关键特征,它允许不同类型的对象根据其公共接口进行互换处理。多态性允许开发人员编写适用于更高级别抽象的代码,而无需处理每个对象的具体实现细节,从而简化了复杂性管理。使用多态性,开发人员可以创建更灵活和可扩展的系统,因为可以添加新类而不会影响现有代码。这促进了模块化和可扩展的开发,从长远来看降低了复杂性。
复杂性管理是软件开发的一个关键方面,面向对象范例为这项任务提供了强大的框架。
通过封装、抽象、继承和多态性等原则,面向对象范式允许开发人员有效地管理复杂性并创建可维护、可扩展和模块化的系统。通过将数据和行为封装在对象中、抽象出不必要的细节、通过继承重用代码以及使用多态性,面向对象范例提供了一种管理复杂性的综合方法。面向对象范式的使用极大地改进了软件开发过程,并有助于创建可靠且可管理的软件系统。
编程艺术将科学原理与创造力、解决问题和创新相结合。这是一门既需要技术实力又需要艺术视野的学科。使用面向对象的方法管理复杂性在编程中至关重要,它使程序员能够开发出优雅而高效的解决方案,改善用户体验,并对社会产生持久的影响。
随着技术的进步,软件将继续塑造我们的数字世界并推动未来的创新。