跳转到内容

优化 C++/通用优化技术/其他技术

来自维基教科书,开放的书籍,为开放的世界

查询游标

[编辑 | 编辑源代码]

不要定义一个返回集合(也称为快照)的函数,而要定义一个返回迭代器(也称为游标动态集)的函数,您可以使用它来生成或可能更改所需数据。

此技术对于数据库查询特别有用,但也适用于内部数据结构。

假设您有一个封装在类中的集合(或一组集合)。该类公开了一个或多个成员函数来从该集合中提取(或过滤)一个子集。

一种获取它的方法是构造一个新的集合,将提取的数据复制到其中,然后返回该集合。在数据库术语中,这种集合被称为快照

这种技术有效但效率低下,因为快照的分配和复制需要大量时间和存储空间。此外,它还有一个缺点,即在所有数据都被提取之前,您无法继续处理已经提取的数据。

这里有一个等效但效率更高的技术。

查询函数返回一个迭代器。在数据库术语中,这种迭代器被称为游标动态集。调用者使用这种迭代器一次提取一个被过滤的数据,并可能更改它们。

请注意,这个解决方案并不完全等效,因为如果在迭代器使用过程中,集合被另一个函数调用(可能是来自另一个线程)更改,则迭代器可能被无效化,或者只是被过滤的集合不符合指定条件。因此,您只能在确定底层集合在迭代器整个生命周期内不会以任何方式更改(除了迭代器本身)的情况下应用此技术。

这种技术与编程语言无关,因为迭代器概念是一个抽象设计模式。

[编辑 | 编辑源代码]

如果您需要在很少改变的集合中进行多次搜索,而不是使用搜索树或哈希表,如果您将数据放入数组,对数组进行排序,并在其上执行二分搜索,则可以提高速度。

数组上的二分搜索具有对数复杂度,与搜索树一样,但具有数组典型的紧凑性和局部性引用优势。

如果数组发生了改变,只要改变的频率远低于搜索频率,这个算法仍然具有竞争力。

如果每个集合更改都包含很少的元素插入或更改或删除,则最好在每次更改操作时移动数组。相反,如果集合更改更繁琐,则最好重新创建并对整个数组进行排序。

在 C++ 中,如果数组长度不是编译时常量,请使用 vector

单链表

[编辑 | 编辑源代码]

如果对于列表,您不需要双向迭代器,也不需要在当前元素的末尾或之前插入元素,并且您不需要知道列表中存在多少元素,请使用单链表,而不是双链表

这种容器虽然有很多缺点,但占用的空间更少,速度也更快。

通常,双链表的表头包含指向列表头的指针,指向尾部的指针,以及元素计数器,而单链表的表头只包含指向列表头的指针。此外,通常,双链表的每个节点都包含一个指向前一个节点的指针和一个指向下一个节点的指针,而单链表的每个节点只包含一个指向下一个节点的指针。最后,在双链表中插入每个元素都必须更新四个指针并增加一个计数器,而在单链表中插入每个元素只需要更新两个指针。

在 C++ 标准库中,std::list 容器由双链表实现。slist 容器是非标准的,但在各种库中可用,以及forward_list 容器,它将在 C++11 标准库中可用,由单链表实现。

华夏公益教科书