Hello 算法 1.0.0b2 C++版通常情况下,空间复杂度统计范围是「暂存空间」+「输出空间」。 暂存空间可分为三个部分: ‧「暂存数据」用于保存算法运行中的各种 常量、变量、对象 等。 ‧「栈帧空间」用于保存调用函数的上下文数据。系统每次调用函数都会在栈的顶部创建一个栈帧,函数返 回时,栈帧空间会被释放。 ‧「指令空间」用于保存编译后的程序指令,在实际统计中一般忽略不计。 Figure 2‑9. 算法使用的相关空间 /* 结构体 ,根据算法需求选用,即在满足取值范围的情况下尽 量减小内存空间占用; ‧「浮点数」代表小数,根据长度分为 float, double ,同样根据算法的实际需求选用; ‧「字符」在计算机中是以字符集的形式保存的,char 的值实际上是数字,代表字符集中的编号,计算机 通过字符集查表来完成编号到字符的转换。占用空间通常为 2 bytes 或 1 byte ; ‧「布尔」代表逻辑中的“是”与“否”,其占用空间需根据编程语言确定,通常为 nullptr; head = head->next; 4. 数组与链表 hello‑algo.com 52 } return head; } 链表的内存占用多。链表以结点为单位,每个结点除了保存值外,还需额外保存指针(引用)。这意味着同样 数据量下,链表比数组需要占用更多内存空间。 4.2.3. 链表常用操作 遍历链表查找。遍历链表,查找链表内值为 target 的结点,输出结点在链表中的索引。0 码力 | 197 页 | 15.72 MB | 1 年前3
Hello 算法 1.0.0b1 C++版通常情况下,空间复杂度统计范围是「暂存空间」+「输出空间」。 暂存空间可分为三个部分: ‧「暂存数据」用于保存算法运行中的各种 常量、变量、对象 等。 ‧「栈帧空间」用于保存调用函数的上下文数据。系统每次调用函数都会在栈的顶部创建一个栈帧,函数返 回时,栈帧空间会被释放。 ‧「指令空间」用于保存编译后的程序指令,在实际统计中一般忽略不计。 Figure 2‑9. 算法使用的相关空间 /* 结构体 ,根据算法需求选用,即在满足取值范围的情况下尽 量减小内存空间占用; ‧「浮点数」代表小数,根据长度分为 float, double ,同样根据算法的实际需求选用; ‧「字符」在计算机中是以字符集的形式保存的,char 的值实际上是数字,代表字符集中的编号,计算机 通过字符集查表来完成编号到字符的转换。占用空间与具体编程语言有关,通常为 2 bytes 或 1 byte ; ‧「布尔」代表逻辑中的 nullptr; head = head->next; 4. 数组与链表 hello‑algo.com 52 } return head; } 链表的内存占用多。链表以结点为单位,每个结点除了保存值外,还需额外保存指针(引用)。这意味着同样 数据量下,链表比数组需要占用更多内存空间。 4.2.3. 链表常用操作 遍历链表查找。遍历链表,查找链表内值为 target 的结点,输出结点在链表中的索引。0 码力 | 187 页 | 14.71 MB | 1 年前3
Hello 算法 1.0.0b4 C++版通常情况下,空间复杂度统计范围是「暂存空间」+「输出空间」。 暂存空间可以进一步划分为三个部分: ‧「暂存数据」用于保存算法运行过程中的各种常量、变量、对象等。 ‧「栈帧空间」用于保存调用函数的上下文数据。系统在每次调用函数时都会在栈顶部创建一个栈帧,函 数返回后,栈帧空间会被释放。 ‧「指令空间」用于保存编译后的程序指令,在实际统计中通常忽略不计。 因此,在分析一段程序的空间复杂度时,我们一般统计 暂存数据、输出数据、栈帧空间 (树) 数据结构。 � char 类型的长度是 1 byte 吗? char 类型的长度由编程语言采用的编码方法决定。例如,Java, JS, TS, C# 都采用 UTF‑16 编 码(保存 Unicode 码点),因此 char 类型的长度为 2 bytes 。 50 4. 数组与链表 4.1. 数组 「数组 Array」是一种线性数据结构,其将相同类型元素存储在连续的内存空间中。我们将元素在数组中的位 == nullptr) return nullptr; head = head->next; } return head; } 链表的内存占用较大。链表以节点为单位,每个节点除了保存值之外,还需额外保存指针(引用)。这意味着 在相同数据量的情况下,链表比数组需要占用更多的内存空间。 4.2.3. 链表常用操作 遍历链表查找。遍历链表,查找链表内值为 target 的节点,输出节点在链表中的索引。0 码力 | 343 页 | 27.39 MB | 1 年前3
Hello 算法 1.1.0 C++ 版间效率上与迭代相当。这种情况被称为尾递归(tail recursion)。 ‧ 普通递归:当函数返回到上一层级的函数后,需要继续执行代码,因此系统需要保存上一层调用的上下 文。 ‧ 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无须继续执行其他 操作,因此系统无须保存上一层函数的上下文。 以计算 1 + 2 + ⋯ + ? 为例,我们可以将结果变量 res 设为函数参数,从而实现尾递归: 一般情况下,空间复杂度的统计范围是“暂存空间”加上“输出空间”。 暂存空间可以进一步划分为三个部分。 ‧ 暂存数据:用于保存算法运行过程中的各种常量、变量、对象等。 ‧ 栈帧空间:用于保存调用函数的上下文数据。系统在每次调用函数时都会在栈顶部创建一个栈帧,函数 返回后,栈帧空间会被释放。 ‧ 指令空间:用于保存编译后的程序指令,在实际统计中通常忽略不计。 在分析一段程序的空间复杂度时,我们通常统计暂存数据、栈帧空间和输出数据三部分,如图 )。 Q:char 类型的长度是 1 字节吗? char 类型的长度由编程语言采用的编码方法决定。例如,Java、JavaScript、TypeScript、C# 都采用 UTF‑16 编码(保存 Unicode 码点),因此 char 类型的长度为 2 字节。 Q:基于数组实现的数据结构也称“静态数据结构”是否有歧义?栈也可以进行出栈和入栈等操作,这些操 作都是“动态”的。 栈确实可0 码力 | 379 页 | 18.47 MB | 1 年前3
Hello 算法 1.0.0b5 C++版间效率上与迭代相当。这种情况被称为「尾递归 tail recursion」。 ‧ 普通递归:当函数返回到上一层级的函数后,需要继续执行代码,因此系统需要保存上一层调用的上下 文。 ‧ 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无需继续执行其他 操作,因此系统无需保存上一层函数的上下文。 以计算 1 + 2 + ⋯ + ? 为例,我们可以将结果变量 res 设为函数参数,从而实现尾递归。 一般情况下,空间复杂度的统计范围是“暂存空间”加上“输出空间”。 暂存空间可以进一步划分为三个部分。 ‧ 暂存数据:用于保存算法运行过程中的各种常量、变量、对象等。 ‧ 栈帧空间:用于保存调用函数的上下文数据。系统在每次调用函数时都会在栈顶部创建一个栈帧,函数 返回后,栈帧空间会被释放。 ‧ 指令空间:用于保存编译后的程序指令,在实际统计中通常忽略不计。 在分析一段程序的空间复杂度时,我们通常统计暂存数据、栈帧空间和输出数据三部分。 )和非线性 (树)数据结构。 � char 类型的长度是 1 byte 吗? char 类型的长度由编程语言采用的编码方法决定。例如,Java、JS、TS、C# 都采用 UTF‑16 编码(保存 Unicode 码点),因此 char 类型的长度为 2 bytes 。 63 第 4 章 数组与链表 � 数据结构的世界如同一堵厚实的砖墙。 数组的砖块整齐排列,逐个紧贴。链表的砖块分0 码力 | 377 页 | 30.69 MB | 1 年前3
Hello 算法 1.0.0 C++版间效率上与迭代相当。这种情况被称为「尾递归 tail recursion」。 ‧ 普通递归:当函数返回到上一层级的函数后,需要继续执行代码,因此系统需要保存上一层调用的上下 文。 ‧ 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无须继续执行其他 操作,因此系统无须保存上一层函数的上下文。 以计算 1 + 2 + ⋯ + ? 为例,我们可以将结果变量 res 设为函数参数,从而实现尾递归: 一般情况下,空间复杂度的统计范围是“暂存空间”加上“输出空间”。 暂存空间可以进一步划分为三个部分。 ‧ 暂存数据:用于保存算法运行过程中的各种常量、变量、对象等。 ‧ 栈帧空间:用于保存调用函数的上下文数据。系统在每次调用函数时都会在栈顶部创建一个栈帧,函数 返回后,栈帧空间会被释放。 ‧ 指令空间:用于保存编译后的程序指令,在实际统计中通常忽略不计。 在分析一段程序的空间复杂度时,我们通常统计暂存数据、栈帧空间和输出数据三部分,如图 )。 Q:char 类型的长度是 1 字节吗? char 类型的长度由编程语言采用的编码方法决定。例如,Java、JavaScript、TypeScript、C# 都采用 UTF‑16 编码(保存 Unicode 码点),因此 char 类型的长度为 2 字节。 Q:基于数组实现的数据结构也称“静态数据结构”是否有歧义?栈也可以进行出栈和入栈等操作,这些操 作都是“动态”的。 栈确实可0 码力 | 378 页 | 17.59 MB | 1 年前3
现代C++ 教程:高速上手C++11/14/17/20<< std::endl; // 这时, stored_value == 1, 而 value == 100. // 因为 copy_value 在创建时就保存了一份 value 的拷贝 } 2. 引用捕获 与引用传参类似,引用捕获保存的是引用,值会发生变化。 void lambda_reference_capture() { int value = 1; 34 3.1 Lambda "stored_value = " << stored_value << std::endl; // 这时, stored_value == 100, value == 100. // 因为 copy_value 保存的是引用 } 3. 隐式捕获 手动书写捕获列表有时候是非常复杂的,这种机械性的工作可以交给编译器来处理,这时 候可以在捕获列表中写一个 & 或 = 向编译器声明采用引用捕获或者值捕获. 总结一下,捕获提供了 40 3.3 右值引用 第 3 章语言运行期的强化 double s = 1; increase(s); } 由于 int& 不能引用 double 类型的参数,因此必须产生一个临时值来保存 s 的值,从而当 increase() 修改这个临时值时,调用完成后 s 本身并没有被修改。 第二个问题,为什么常量引用允许绑定到非左值?原因很简单,因为 Fortran 需要。 移动语义0 码力 | 83 页 | 2.42 MB | 1 年前3
Hello 算法 1.2.0 简体中文 C++ 版间效率上与迭代相当。这种情况被称为尾递归(tail recursion)。 ‧ 普通递归:当函数返回到上一层级的函数后,需要继续执行代码,因此系统需要保存上一层调用的上下 文。 ‧ 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无须继续执行其他 操作,因此系统无须保存上一层函数的上下文。 以计算 1 + 2 + ⋯ + ? 为例,我们可以将结果变量 res 设为函数参数,从而实现尾递归: 一般情况下,空间复杂度的统计范围是“暂存空间”加上“输出空间”。 暂存空间可以进一步划分为三个部分。 ‧ 暂存数据:用于保存算法运行过程中的各种常量、变量、对象等。 ‧ 栈帧空间:用于保存调用函数的上下文数据。系统在每次调用函数时都会在栈顶部创建一个栈帧,函数 返回后,栈帧空间会被释放。 ‧ 指令空间:用于保存编译后的程序指令,在实际统计中通常忽略不计。 在分析一段程序的空间复杂度时,我们通常统计暂存数据、栈帧空间和输出数据三部分,如图 )。 Q:char 类型的长度是 1 字节吗? char 类型的长度由编程语言采用的编码方法决定。例如,Java、JavaScript、TypeScript、C# 都采用 UTF‑16 编码(保存 Unicode 码点),因此 char 类型的长度为 2 字节。 Q:基于数组实现的数据结构也称“静态数据结构”是否有歧义?栈也可以进行出栈和入栈等操作,这些操 作都是“动态”的。 栈确实可0 码力 | 379 页 | 18.48 MB | 10 月前3
C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅队列里取出数据,即“认领任务”。然后执行,执行 完毕后才去认领下一个任务,从而即使每个任务 工作量不一也能自动适应。 • 这种技术又称为线程池( thread pool ),避免了 线程需要保存上下文的开销。但是需要我们管理 一个任务队列,而且要是线程安全的队列。 struct Task { int x0, y0; int nx, ny; }; std::queue识到无法再追加新数据。这时他会重新 malloc 一段更大的连续内存,使得 capacity 变成 size 的两倍,并且把旧的数据移动过去,然后继续追 加数据。 • 这就导致前半段的元素的地址被改变,从而导致 之前保存的指针和迭代器失效。 reserve 预留足够的 capacity • 如果预先知道 size 最后会是 n ,则可以 调用 reserve(n) 预分配一段大小为 n 的 内存,从而 capacity 0 码力 | 116 页 | 15.85 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 13 C++ STL 容器全解之 vector样,同样因为返回的是一个左值引用所以还可以继续 自增比如 ++++p 。 • p++ 会返回自增前的值 p ,但是执行完以后 p 却又 是 p + 1 了,非常迷惑) • 正因如此,后置自增需要先保存旧的迭代器,然后自 增自己,再返回旧迭代器,可能会比较低效。 • 在 C++ 中我推荐尽可能地多用前置自增 ++p 。 在运算符重载上,沙雕的 C++ 标准 委员会规定, operator++(int) 只往尾部插入元素。如果需要高效的头部插入,可以考虑用 deque 容器,他有高效的 push_front 函数替代。 • insert 在容量不足时,同样会造成重新分配以求扩容,会移 动其中所有元素,这时所有之前保存的迭代器都会失效。 vector 容器: insert 函数,插到指定的元素前方 • 如果要插入到一个特定位置,可以用迭代 器的加法来获取某一位置的迭代器。 • 例如 a.begin() +0 码力 | 90 页 | 4.93 MB | 1 年前3
共 17 条
- 1
- 2













