c++之STL详解

c++之STL详解

  • 泛型编程
  • 什么是STL
  • STL发展
  • STL组件
  • 容器
  • 类型成员
  • 适配器
  • STL迭代器
  • STL算法
  • 顺序容器
  • 向量vector
  • 双端队列
  • 双端队列实现
  • 列表list
  • c++关联容器
  • c++map
  • multimap
  • set
  • multiset
  • 迭代器
  • 函数对象
  • 集成函数对象
  • 自定义函数对象
  • 标准c++库中算法
  • STL算法头文件
  • 标准函数
  • 泛型算法例子
  • 自定函数作为算法参数

泛型编程

泛型编程是一种编程方法,它允许程序员编写通用的代码,即可适用于不同的数据类型,而不必为每种类型编写不同的代码。这种编程方法的基本思想是将数据类型抽象化,使用泛型来表示数据类型,并在编写代码时使用泛型来代替具体的数据类型。

Java、C#等编程语言都支持泛型编程。在Java中,泛型可以用于类、接口、方法等,可以确保代码的类型安全,并提高代码的重用性和可读性。泛型编程可以用于各种领域,例如集合类、算法实现、网络编程等。

什么是STL

STL是C++标准库中的一个模板库,它提供了一系列的通用数据结构和算法,包括容器、迭代器、算法、函数对象等等。STL 的全称是 Standard Template Library(标准模板库),它是C++程序员经常使用的一个工具箱。STL 的主要目的是提高开发效率和代码质量,使得程序员可以更加便捷地完成常见的操作。

STL发展

STL是一种C++的标准库,用于实现常用的数据结构和算法。它的发展历程可以从以下几个方面来讨论:

  1. 早期版本:STL最初由Alexander Stepanov和Meng Lee于1994年开发,最初被称为SGI STL(Silicon Graphics Inc. STL)。它的目的是为了在C++中提供高效的数据结构和算法的实现,大大简化了C++程序的开发。早期版本的STL包含容器、迭代器、算法、函数对象等组件。

  2. 标准化:由于STL在C++社区中的广泛应用,它于1998年正式被纳入C++标准库中。这一标准化使得STL更加稳定和可靠,成为C++程序员必备的工具之一。

  3. 扩展和优化:随着C++标准的不断更新,STL也不断得到扩展和优化。例如,C++11标准中新增了多线程支持,同时STL也在容器、迭代器、算法等方面得到了进一步扩展和优化。此外,一些开源社区也提供了STL的优化版本,如boost库、Eastl等。

  4. 应用领域:STL在软件开发中有广泛的应用,包括游戏开发、图形处理、科学计算、数据挖掘等领域。尤其在高性能和高并发的系统开发中,STL的应用更加广泛。

总的来说,STL的发展历程是一个不断完善和拓展的过程,它为C++程序员提供了强大的工具,极大地提高了程序开发效率和性能。

STL组件

STL(标准模板库)是C++的一个重要组件,它是由一组通用的模板类和函数组成的,并且提供了一些常用的数据结构和算法,如动态数组(vector)、链表(list)、集合(set)、映射(map)、排序、查找等。STL的设计思想是将数据结构和算法进行分离,使得它们可以独立使用和扩展,提高了代码的复用性和可读性。

STL主要包含以下组件:

  1. 容器(Containers):动态数组(vector)、链表(list)、双端队列(deque)、队列(queue)、堆栈(stack)、集合(set)、映射(map)等。

  2. 迭代器(Iterators):是一种抽象的数据类型,可用于访问容器中的元素,STL提供了五种迭代器类型,包括输入迭代器(Input Iterator)、输出迭代器(Output Iterator)、前向迭代器(Forward Iterator)、双向迭代器(Bidirectional Iterator)和随机访问迭代器(Random Access Iterator)。

  3. 算法(Algorithms):STL提供了大量的常用算法,包括排序、查找、合并、去重、计数、查找等等。

  4. 函数对象(Function Objects):STL中的函数对象是一种封装了函数或函数指针的对象,它可以像函数一样被调用,也可以像对象一样被赋值或传递给其他函数,常用的函数对象有谓词(Predicate)和函数适配器(Function Adapters)。

  5. 适配器(Adaptors):STL提供了一些适配器,用于将一些数据结构转换为另一些数据结构,包括容器适配器(Container Adaptors)、迭代器适配器(Iterator Adapters)和函数适配器(Function Adapters)。

容器

STL(Standard Template Library)是C++中的一种标准库,它提供了多种容器类型用于存储数据。下面是STL容器的一些常见类型:

  1. vector:可以动态调整大小的数组,支持快速的随机访问和迭代器访问,并且支持在尾部添加或删除元素。

  2. deque:双端队列,支持快速的随机访问和迭代器访问,并且支持在头部和尾部添加或删除元素。

  3. list:双向链表,只支持迭代器访问,并且支持在任意位置添加或删除元素。

  4. set:有序集合,其中每个元素都是唯一的,支持快速的查找和插入操作。

  5. map:有序映射,其中每个元素都有一个唯一的键值对,支持快速的查找和插入操作。

  6. unordered_set:无序集合,其中每个元素都是唯一的,支持快速的查找和插入操作,但元素的顺序是未定义的。

  7. unordered_map:无序映射,其中每个元素都有一个唯一的键值对,支持快速的查找和插入操作,但元素的顺序是未定义的。

以上仅是STL容器的一部分,其中还包括stack、queue、priority_queue等等。不同的容器类型适用于不同的使用场景,需要根据实际情况进行选择。

类型成员

STL中的类型成员是指类型别名,这些类型别名被定义在各个STL组件中,用于简化代码和提高可读性。以下是一些常用的STL类型成员:

  1. value_type:表示容器中元素的类型。
  2. allocator_type:表示容器使用的内存分配器的类型。
  3. difference_type:表示两个迭代器之间的距离所使用的类型。
  4. size_type:表示容器的大小的类型。
  5. key_type:表示关联容器中键的类型。
  6. mapped_type:表示关联容器中值的类型。
  7. pointer:表示指向容器中元素的指针类型。
  8. reference:表示容器中元素的引用类型。
  9. iterator:表示容器的迭代器类型。
  10. const_iterator:表示容器的只读迭代器类型。
  11. reverse_iterator:表示容器的反向迭代器类型。
  12. const_reverse_iterator:表示容器的只读反向迭代器类型。

适配器

STL(Standard Template Library)适配器是一项功能强大的编程技术,用于将一种容器类型适配到另一种容器类型上。STL适配器允许开发人员轻松地使用不同类型的容器,而无需更改代码或重新编写算法。

常见的STL适配器包括:

  1. 迭代器适配器:将一个迭代器转换为另一个迭代器,例如反向迭代器、插入迭代器和流迭代器。

  2. 容器适配器:将一种容器类型适配成另一种容器类型,例如stack、queue和priority_queue。

  3. 函数适配器:将一种函数类型适配成另一种函数类型,例如bind和mem_fn。

STL适配器的优点在于可以提高代码的可重用性和可维护性,同时简化了开发人员的工作。

STL迭代器

STL迭代器是一种用于遍历和访问STL容器(如vector、list等)中元素的对象。它类似于指针,但比指针更灵活。迭代器有不同的类型,每种类型对应不同的容器类型,如输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器等。迭代器可以实现容器中元素的添加、删除、修改和查询操作,使得对于任何STL容器的操作都可以写成通用的代码。使用迭代器可以避免直接操作容器而引起的风险,同时也提高了代码的可复用性和可维护性。

STL算法

STL(Standard Template Library)是一种C++语言的标准库,其中包含了很多常用的数据结构和算法。STL中的算法库提供了很多种算法,可以用来处理各种数据结构,例如数组、列表、栈、队列等等。以下是STL中常用的算法:

  1. 查找算法:find、find_if、binary_search等

  2. 排序算法:sort、stable_sort、partial_sort等

  3. 操作算法:copy、swap、reverse等

  4. 数值算法:accumulate、inner_product、partial_sum等

  5. 集合算法:merge、set_union、set_intersection等

  6. 变异算法:transform、replace、remove等

  7. 分类算法:partition、stable_partition、is_sorted等

STL算法库的使用非常方便,只需要include相应的头文件就可以了,如#include。STL算法的时间复杂度和空间复杂度均已经得到了优化,因此在面对大规模数据处理时,使用STL算法库可以大大提高程序的效率。

顺序容器

STL顺序容器是指能够按照元素的顺序存储和访问元素的容器,包括以下几种:

  1. vector:动态数组,支持在末尾添加和删除元素,也支持随机访问。
  2. deque:双端队列,支持在两端添加和删除元素,也支持随机访问。
  3. list:双向链表,支持在任意位置添加和删除元素,但不支持随机访问。
  4. forward_list:单向链表,支持在任意位置添加和删除元素,但不支持随机访问。
  5. array:静态数组,固定大小,不支持添加和删除元素,但支持随机访问。

这些容器都是通过模板类实现的,可以存储各种类型的元素。它们都提供了一些常用的操作方法,如访问元素、添加和删除元素、查找元素等。开发者可以根据具体的需求选择合适的容器进行使用。

向量vector

向量(vector)是指在数学中,一个由数量(也可称为标量)组成的有序组,常用于表示物理量的大小和方向。常见的向量表示方式为箭头表示法,箭头的长度表示数量的大小,箭头的方向表示向量的方向。

向量可以进行加法、减法、数量乘法和点乘等运算,在三维空间中向量可以表示为一个由三个实数组成的有序组。向量在物理学、工程学、计算机科学、经济学等领域都有广泛的应用。

双端队列

双端队列(Double-ended Queue,缩写为Deque)是一种具有队列和栈的性质的数据结构。它支持在两端进行插入和删除操作,因此可以从队列和栈两个方向来操作数据。在双端队列中,可以在队列的头部和尾部添加或删除元素。

双端队列同样支持队列的先进先出(FIFO)特性,因此可以作为一个队列来使用。同时,由于它支持栈的后进先出(LIFO)特性,因此也可以作为一个栈来使用。

在Python中,双端队列可以通过标准库collections中的deque类来实现。它支持的操作包括从队列头部和尾部进行添加和删除操作,以及队列元素的访问、查找、计数和翻转等。

双端队列实现

双端队列(Double Ended Queue,简称Deque)是一种可以从两端添加、删除元素的线性数据结构。双端队列可以看作是栈和队列的结合体,支持在队列头和队列尾进行插入和删除操作。

双端队列的实现可以用数组或链表来实现。以下是使用数组实现的双端队列示例代码:

class Deque:def __init__(self):self.items = []def add_front(self, item):"""在队头添加元素"""self.items.insert(0, item)def add_rear(self, item):"""在队尾添加元素"""self.items.append(item)def remove_front(self):"""在队头删除元素"""if self.is_empty():return Nonereturn self.items.pop(0)def remove_rear(self):"""在队尾删除元素"""if self.is_empty():return Nonereturn self.items.pop()def is_empty(self):"""判断队列是否为空"""return len(self.items) == 0def size(self):"""返回队列大小"""return len(self.items)

在上述代码中,我们使用 Python 的内置列表作为底层数据结构来实现双端队列。具体实现方式如下:

  • add_front 方法使用 list.insert() 在队头添加元素。
  • add_rear 方法使用 list.append() 在队尾添加元素。
  • remove_front 方法使用 list.pop(0) 删除队头元素。
  • remove_rear 方法使用 list.pop() 删除队尾元素。
  • is_empty 方法通过 len() 判断队列是否为空。
  • size 方法通过 len() 返回队列大小。

这是双端队列的基本实现,稍加修改即可用链表实现。

列表list

C++中的列表(list)是一个双向链表,它是一个STL标准库提供的容器类型,可以在程序中使用。列表可以存储多个元素,可以在任意位置插入或删除元素,也可以对其进行遍历。

以下是列表的一些常用操作:

  1. 创建列表:可以使用默认构造函数或者将另一个列表作为参数传递给构造函数。
#include <list>
using namespace std;list<int> mylist; // 创建一个空列表
list<int> mylist2(mylist); // 将 mylist 复制给 mylist2
  1. 插入元素:可以在列表任意位置插入元素。
mylist.push_back(10); // 在列表尾部插入元素
mylist.push_front(20); // 在列表头部插入元素
list<int>::iterator it = mylist.begin();
advance(it, 2); // 将迭代器移动到第3个元素后面
mylist.insert(it, 30); // 在第3个元素后面插入元素
  1. 删除元素:可以删除列表的任意一个元素或者一段元素。
mylist.pop_back(); // 删除列表尾部的元素
mylist.pop_front(); // 删除列表头部的元素
list<int>::iterator it = mylist.begin();
advance(it, 2); // 将迭代器移动到第3个元素
mylist.erase(it); // 删除第3个元素
mylist.erase(mylist.begin(), mylist.end()); // 删除整个列表中的元素
  1. 遍历列表:可以使用迭代器来遍历列表中的元素。
for (list<int>::iterator it = mylist.begin(); it != mylist.end(); ++it) {cout << *it << endl;
}

以上是常用的一些操作,除此之外,列表还提供了许多其他的操作,如排序、翻转等。

c++关联容器

C++关联容器是一种按照键值对存储元素的容器,其中每个元素都有一个唯一的键值。常见的关联容器包括map、multimap、set和multiset。

map和multimap用于存储键值对,其中map中键值对的键是唯一的,而在multimap中键可以重复出现。set和multiset用于存储唯一的键值,其中set中键是唯一的,而在multiset中键可以重复出现。

关联容器的常见操作包括插入、删除、查找和遍历。插入操作可以使用insert()函数,删除操作可以使用erase()函数,查找操作可以使用find()函数,遍历操作可以使用迭代器实现。关联容器还支持排序、计数和范围查找等高级操作。

关联容器是C++语言中常用的容器之一,适用于需要快速查找和按键排序的场景。

c++map

C++ 中的 map 是一种关联式容器,它将键映射到值。每个键只能对应一个值。map 内部按照一定的顺序存储键值对,通过键可以快速查找对应的值。

map 的使用需要包含头文件 map。以下是一些常用的 map 操作:

  1. 插入元素:使用 insert() 函数或 [] 运算符,用键值对的形式插入元素。

    map<int, string> myMap;
    myMap.insert(pair<int, string>(1, "apple"));
    myMap[2] = "banana";
    
  2. 查找元素:使用 find() 函数查找指定键所对应的值,如果找到返回迭代器,否则返回 map::end 迭代器。

    auto it = myMap.find(1);
    if (it != myMap.end()) {cout << it->second << endl;
    }
    
  3. 删除元素:使用 erase() 函数删除指定键所对应的键值对。

    myMap.erase(1);
    
  4. 遍历元素:使用迭代器遍历整个 map。

    for (auto it = myMap.begin(); it != myMap.end(); ++it) {cout << it->first << " " << it->second << endl;
    }
    

map 内部使用红黑树实现,因此插入、删除、查找操作的时间复杂度均为 O(log n)。需要注意的是,因为 map 内部存储的是键值对,因此在使用迭代器遍历时需要使用 it->first 和 it->second 访问键和值。

multimap

multimap是C++ STL库中的一个关联容器,它允许存储键值对,其中一个键可以映射到多个值。multimap内部维护一个红-黑树,以保证元素的顺序性和快速查找。

multimap的使用与map相似,但允许某一个键对应多个值。multimap的常用操作包括插入元素、删除元素、查找元素等操作。

下面是一个简单的示例,展示如何使用multimap来存储学生的姓名和成绩信息:

#include <iostream>
#include <map>int main()
{std::multimap<std::string, int> grades;// 添加学生信息grades.insert(std::make_pair("小明", 80));grades.insert(std::make_pair("小明", 85));grades.insert(std::make_pair("小红", 90));grades.insert(std::make_pair("小红", 95));grades.insert(std::make_pair("小李", 75));// 输出学生信息for (auto& student : grades){std::cout << student.first << " " << student.second << std::endl;}return 0;
}

输出结果为:

小明 80  
小明 85  
小红 90  
小红 95  
小李 75

可以看到,可以用multimap存储同一键对应的多个值,并且按照键值对的顺序输出结果。

set

C++中的Set是一种基于红黑树实现的数据结构,它可以用来存储不重复的元素,并且提供了一些查找、添加、删除等操作。

以下是Set的一些常用操作:

  1. 创建Set对象:可以使用以下语法来创建一个空的Set对象:

    std::set<int> mySet;
    
  2. 插入元素:使用 insert() 方法可以向集合添加新元素,如下所示:

    mySet.insert(10);
    
  3. 删除元素:使用 erase() 方法可以从集合中删除元素,如下所示:

    mySet.erase(10);
    
  4. 查找元素:使用 find() 方法可以查找集合中的元素,如下所示:

    auto it = mySet.find(10);
    if (it != mySet.end()) {// 元素存在
    }
    
  5. 遍历集合:使用迭代器可以遍历集合中的元素,如下所示:

    for (auto i = mySet.begin(); i != mySet.end(); ++i) {std::cout << *i << " ";
    }
    

Set还提供了一些其他的方法,如判断集合是否为空、获取集合元素个数等,有需要的话可以查看相关文档。

multiset

C++中的multiset是一个容器,它可以将多个相同类型的元素存储在一个集合中,并且其中的每个元素都可以有多个副本。multiset由标准模板库(STL)提供支持,并且是一个有序的容器,插入元素的顺序决定了它们在容器中的位置。

multiset使用红黑树实现,因此它可以提供快速的插入、查找和删除操作,并且可以保持元素的有序状态。它提供了一系列的成员函数,例如insert()、erase()、find()、count()、size()等,可以对集合中的元素进行操作。

multiset可以存储重复元素,因此它在某些情况下非常有用。例如,如果您需要对一组元素进行排序,并且其中可能存在重复元素,则可以使用multiset来存储这些元素。

以下是一个使用multiset的示例代码:

#include <iostream>
#include <set>using namespace std;int main()
{multiset<int> myset;myset.insert(10);myset.insert(20);myset.insert(30);myset.insert(20);myset.insert(40);cout << "The multiset contains: ";for (auto it = myset.begin(); it != myset.end(); it++){cout << *it << " ";}cout << endl;cout << "The number of elements with value 20 is: " << myset.count(20) << endl;myset.erase(20);cout << "The multiset after erasing element with value 20 contains: ";for (auto it = myset.begin(); it != myset.end(); it++){cout << *it << " ";}cout << endl;return 0;
}

输出结果:

The multiset contains: 10 20 20 30 40 
The number of elements with value 20 is: 2
The multiset after erasing element with value 20 contains: 10 30 40 

迭代器

迭代器(Iterator)是一种设计模式,在遍历一个集合(如数组、链表、集合等)时,提供一种遍历方式,而不需要暴露内部实现。通过迭代器,我们可以逐个访问集合中的元素,而不需要知道实际存储结构或者底层数据类型。

迭代器模式的核心是将集合对象和遍历算法分离,使得集合对象和遍历算法能够独立地变化。迭代器模式定义了一个迭代器接口,包含了遍历集合所需要的方法,如获取下一个元素、判断是否还有下一个元素等。各个集合类实现此接口,提供自己的迭代器实现。

在 Java 中,迭代器通常使用 Iterator 接口来实现,此接口包括 hasNext(),next(),remove() 等方法。对于集合类对象,可以通过调用其 iterator() 方法获得迭代器对象,然后通过调用 next() 方法来逐个访问集合元素。

函数对象

C++中的函数对象是一个实现了函数调用操作符(operator())的类对象。函数对象可以像函数一样被调用,但是与函数不同的是,函数对象可以有自己的状态和行为,并且可以在调用时接收参数。

函数对象可以用作STL算法中的函数参数,可以增强算法的灵活性和可重用性。此外,函数对象还可以用于模板编程中,用于灵活地定制算法行为。

以下是一个简单的函数对象示例:

class MultiplyBy {
public:MultiplyBy(int factor) : factor_(factor) {}int operator()(int x) const {return x * factor_;}
private:int factor_;
};int main() {MultiplyBy mul3(3);std::cout << mul3(4) << std::endl; // 输出12return 0;
}

在上面的示例中,函数对象MultiplyBy实现了一个乘法操作。它有一个构造函数用于初始化乘数,以及一个重载了函数调用操作符的方法,用于执行乘法操作。

在main函数中,创建了一个MultiplyBy对象mul3,其乘数为3。然后调用函数对象mul3,并将参数4传递给它,最终输出12。

集成函数对象

集成函数对象是指可以对某个给定函数进行积分运算的函数对象。在计算机程序中,集成函数对象常常被用于数值积分算法中,例如梯形法、辛普森法等。常见的集成函数对象包含以下几种:

  1. 梯形法集成函数对象:用于计算函数在区间上的定积分,近似于用梯形面积来计算积分值。

  2. 辛普森法集成函数对象:同样用于计算函数在区间上的定积分,但是使用更高阶的多项式逼近,所以精度更高。

  3. 高斯-勒让德法集成函数对象:使用基于Legendre多项式的数值积分技术,可以高度精确地计算积分值。

  4. 龙格-库塔法集成函数对象:不仅能计算定积分,还能求解微分方程。它在数值计算中被广泛使用。

这些集成函数对象常常需要用户提供被积函数的表达式或者函数指针,以及积分区间的端点,然后返回数值积分结果。

自定义函数对象

自定义函数对象是指可以像普通函数一样被调用的对象,它具有函数对象的所有特征,比如可以被赋值给变量、可以作为参数传递给其他函数、可以在类中定义等。

创建自定义函数对象的步骤如下:

  1. 定义一个类,重载 __call__() 方法,这个方法会在对象被调用时自动执行。

  2. __call__() 方法中编写函数的实现逻辑,可以使用类的属性和方法,也可以使用其他函数。

  3. 创建对象并将其赋值给变量,这样就可以像调用普通函数一样调用自定义函数对象。

示例代码:

class MyFunction:def __init__(self, name):self.name = namedef __call__(self, *args, **kwargs):print(f"Hello, {self.name}!")print(f"args: {args}")print(f"kwargs: {kwargs}")my_func = MyFunction("World")  # 创建对象
my_func("arg1", arg2="value2")  # 调用对象,输出:Hello, World! args: ('arg1',) kwargs: {'arg2': 'value2'}

标准c++库中算法

标准C++库中的算法是一组在范围内(例如,容器或数组)执行各种操作的函数,可以应用于各种数据类型。这些算法通过迭代器进行工作,并提供对排序、搜索、变换、比较、合并等操作的支持。

以下是一些常见的标准C++算法:

  1. sort() - 对范围内的元素进行排序。

  2. find() - 在范围内查找给定值的元素。

  3. transform() - 将范围内的每个元素转换为另一种形式。

  4. accumulate() - 在范围内计算元素的累计值。

  5. copy() - 将范围内的元素复制到另一个范围中。

  6. reverse() - 对范围内的元素进行反转。

  7. fill() - 将范围内的元素设置为给定值。

  8. unique() - 从范围内的元素中删除重复项。

  9. binary_search() - 在已排序的范围内查找给定值的元素。

  10. count() - 计算范围内的元素等于给定值的数量。

以上算法只是标准C++库中的一小部分,还有许多其他有用的算法可用于各种编程任务。

STL算法头文件

STL算法头文件包含了很多用于处理容器和迭代器的函数,包括排序、查找、拷贝、比较、合并等等。

常见的STL算法头文件包括:

  • algorithm:包含了大量的STL算法函数,如sort、find、copy、transform、merge等。
  • numeric:包含了数值算法函数,如accumulate、partial_sum、inner_product等。
  • functional:包含了函数对象,如plus、minus、less、greater等,这些函数对象可以用于STL算法中的比较和转换操作。
  • iterator:包含了STL迭代器相关的一些函数和类型,如back_inserter、istream_iterator、ostream_iterator等。

这些头文件可以通过#include指令引入到我们的代码中,使得我们可以直接使用其中的函数和类型。

标准函数

标准函数通常指的是计算机程序中预定义好的、可重用的函数,通常是由编程语言的标准库提供的函数。这些函数已经被测试过,并且被许多程序员广泛使用,因此它们是安全、可靠的。在编写程序时,使用标准函数可以提高开发效率和程序的可维护性。

例如,在C语言中,标准函数包括printf()、scanf()、malloc()、free()等。在Python语言中,标准函数包括print()、input()、len()、range()等。这些函数具有固定的名称和功能,可以直接调用使用,而不需要开发人员自己编写实现代码。

泛型算法例子

一个常见的泛型算法是std::sort(),它可以对各种类型的数据进行排序。以下是一个对整数向量进行排序的示例:

#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> nums{4, 7, 1, 9, 2, 5};std::sort(nums.begin(), nums.end()); // 排序for (int num : nums) {std::cout << num << " ";}return 0;
}

输出:

1 2 4 5 7 9

在这个例子中,std::sort()被调用来对整数向量进行排序,它不需要了解向量的具体类型,而是使用迭代器来遍历向量并进行排序。这使得std::sort()成为一个非常通用的泛型算法。

自定函数作为算法参数

在 C++ 中,我们可以将自定义函数作为算法的参数。

假设我们有一个自定义函数 compare,这个函数接收两个参数,用于比较两个元素的大小并返回比较结果,如下所示:

bool compare(int a, int b) {return a < b;
}

我们可以使用 std::sort 算法,将一个整数数组按照自定义函数 compare 的规则进行排序,示例代码如下:

#include <iostream>
#include <algorithm>bool compare(int a, int b) {return a < b;
}int main() {int arr[] = {4, 2, 8, 1, 5, 3};int n = sizeof(arr) / sizeof(int);std::sort(arr, arr + n, compare);for (int i = 0; i < n; i++) {std::cout << arr[i] << " ";}return 0;
}

运行上述代码,输出结果为:

1 2 3 4 5 8

std::sort 的第三个参数中指定了自定义函数 compare,这样该算法会按照我们自定义的比较规则来进行排序。同样,我们也可以使用其他算法,比如 std::max_elementstd::min_element 等,来接收自定义函数作为参数。

今天的分享到这里就结束了,感谢大家支持,创作不易,希望大家能给博主个三连
在这里插入图片描述

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

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

相关文章

SNAT与DNAT原理

SNAT和DNAT &#xff08;源地址转换和目标地址转换&#xff09; SNAT&#xff1a;源地址转换。内网到外网转换的是源地址。 DNAT&#xff1a;目标地址转换&#xff1a;外网到内网转换的是目的地址 &#xff08;把内部服务器的ip地址转换成一个所有人都可以访问的地址&#xff0…

【Spring】创建一个Spring项目与Bean对象的存储

目录 一、创建Spring项目 1、创建Maven项目 2、配置maven国内源 3、引入spring依赖 4、添加启动类 二、将Bean对象存储到Spring&#xff08;IoC容器&#xff09; 1、创建Bean对象 2、将Bean存储到spring&#xff08;容器&#xff09;中 3、获取Bean对象 3.1、Applicatio…

详解PHP反射API

PHP中的反射API就像Java中的java.lang.reflect包一样。它由一系列可以分析属性、方法和类的内置类组成。它在某些方面和对象函数相似&#xff0c;比如get_class_vars()&#xff0c;但是更加灵活&#xff0c;而且可以提供更多信息。反射API也可与PHP最新的面向对象特性一起工作&…

信息安全技术工业控制系统安全控制应用指南学习笔记

工业控制系统安全控制基线 根据工业控制系统在国家安全、经济建设、社会生活中的重要程度&#xff0c;遭到破坏后对国家安全、社会秩序、公共利益以及公民、法人和其他组织的合法权益的危害程度等&#xff0c;结合信息安全等级保护标准划分及实施效果分析&#xff0c;结合工业…

ElasticSearch详细操作

ElasticSearch搜索引擎详细操作以及概念 文章目录 ElasticSearch搜索引擎详细操作以及概念 1、_cat节点操作1.1、GET/_cat/nodes&#xff1a;查看所有节点1.2、GET/_cat/health&#xff1a;查看es健康状况1.3_、_GET/_cat/master&#xff1a;查看主节点1.4、GET/_cat/indices&a…

Linux初识网络基础

目录 网络发展 认识“协议 ” 网络协议 OSI七层模型&#xff1a; TCP/IP五层&#xff08;或四层&#xff09;模型 网络传输基本流程 网络传输流程图&#xff1a; 数据包封装和封用 网络中的地址 认识IP地址&#xff1a; 认识MAC地址&#xff1a; 网络发展 1.独立…

2023华数杯数学建模C题思路 - 母亲身心健康对婴儿成长的影响

# 1 赛题 C 题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一&#xff0c;她不仅为婴儿提供营养物质和身体保护&#xff0c; 还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况&#xff0c;如抑郁、焦虑、 压力等&#xff0c;可能会对婴儿的认知、情…

解决树莓派“由于没有公钥,无法验证下列签名“

目录 简介&#xff1a;在换完国内源后&#xff0c;树莓派尝试更新同步/etc/apt/sources.list和/etc/apt/sources.list.d中列出的软件源的软件包版本也就是&#xff08;apt-get update&#xff09;和更新已安装的所有或者指定软件包&#xff08;也即是apt-get upgrade&#xff0…

输入框长度在XSS测试中如何绕过字符长度限制

大家好&#xff0c;这是我编写的第一篇文章&#xff0c;之所以会分享这个故事&#xff0c;是因为我花了几个晚上的时间&#xff0c;终于找到了解决某个问题的方法。故事如下&#xff1a; 几个月前&#xff0c;我被邀请参加一个非公共的漏洞悬赏项目&#xff0c;在初期发现了一些…

科技云报道:财税数字化时代,财务人实现RPA自由了吗?

企业数字化转型&#xff0c;财务是一个重要的切入点。随着数字化业务不断展开&#xff0c;新的系统、流程和数据源被不断引入&#xff0c;财务部门面临的是不断暴增的对账、处理报表、审计等日常工作。 如此大的工作量&#xff0c;即使是经验丰富的资深财务&#xff0c;也难免…

一篇文章,教你彻底掌握接口测试!

什么是接口测试 所谓接口&#xff0c;是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据库的对接。而接口测试&#xff0c;则是通过接口的不同情况下的输入&#xff0c;去对比输出&#xff0c;看看是否满足接口规范所规定的功能、安全以及性能方面…

解决问题:ModuleNotFoundError: No module named ‘mmcv._ext‘,及安装mmcv-full的详细教程

解决问题**ModuleNotFoundError: No module named ‘mmcv._ext’**之前得先搞懂mmcv和mmcv-full的关系。 mmcv 和 mmcv-full 都是针对 PyTorch 的计算机视觉基础库,两者的主要区别是: mmcv 包含了 mmcv 的核心组件,例如运行器、回调函数、可视化工具等,打包体积较小。mmcv-fu…

C#,OpenCV开发指南(01)

C#&#xff0c;OpenCV开发指南&#xff08;01&#xff09; 一、OpenCV的安装1、需要安装两个拓展包&#xff1a;OpenCvSharp4和OpenCvSharp4.runtime.win 二、C#使用OpenCV的一些代码1、需要加头文件2、读取图片3、在图片上画矩形框4、 在图片上画直线 一、OpenCV的安装 1、需…

浅谈新电改背景下电网企业综合能源服务商业模式研究及发展方向

安科瑞 华楠 摘要: 新电改方案实施后&#xff0c;由于输配电价的改革和售电侧的放开&#xff0c;电网企业的盈利模式也随之发生了变化。这就要求电网企业转变服务理念与经营方式&#xff0c;来寻求竞争优势。基于“魏朱六要素商业模式”模型&#xff0c;对电网企业综合能源服务…

在Linux中安装MySQL

在Linux中安装MySQL 检测当前系统中是否安装MySQL数据库 命令作用rpm -qa查询当前系统中安装的所有软件rpm -qa|grep mysql查询当前系统中安装的名称带mysql的软件rpm -qa | grep mariadb查询当前系统中安装的名称带mariadb的软件 RPM ( Red-Hat Package Manager )RPM软件包管理…

【雕爷学编程】 MicroPython动手做(35)——体验小游戏3

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

Docker与DevOps的无敌组合,引爆你的创新潜能

&#x1f3c6;荣誉认证&#xff1a;51CTO博客专家博主、TOP红人、明日之星&#xff1b;阿里云开发者社区专家博主、技术博主、星级博主。 &#x1f4bb;微信公众号&#xff1a;iOS开发上架 &#x1f4cc;本文由iOS开发上架原创&#xff01; &#x1f389;欢迎关注&#x1f50e;…

基于Java+SpringBoot+Vue的篮球论坛系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

TiDB 源码编译之 PD/TiDB Dashboard 篇

作者&#xff1a; ShawnYan 原文来源&#xff1a; https://tidb.net/blog/a16b1d46 TiDB TiDB 是 PingCAP 公司自主设计、研发的开源分布式关系型数据库&#xff0c;是一款同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP) 的融…

解决mvn clean install遇到testng单元测试失败时打包也失败的问题

解决mvn clean install遇到testng单元测试失败时打包也失败的问题 看这个之前请先看这个 Jenkins执行Testng 比如我现在就有一个单元测试失败的项目 执行mvn clean install的时候就会报错 下面是我现在的pom.xml 但我们不希望这样&#xff0c;怎么办 <plugin><gr…