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 None
        return self.items.pop(0)

    def remove_rear(self):
        """在队尾删除元素"""
        if self.is_empty():
            return None
        return self.items.pop()

    def is_empty(self):
        """判断队列是否为空"""
        return len(self.items) == 0

    def 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; // 输出12
    return 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 = name
    
    def __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 等,来接收自定义函数作为参数。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器学习深度学习——卷积神经网络(LeNet)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——池化层 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮助 卷积神…

JMeter源码解析之结果收集器

JMeter源码解析之结果收集器 一、JMeter结果收集器概述二、单机模式三、分布式模式四、总结 一、JMeter结果收集器概述 JMeter是在压力领域中最常见的性能测试工具&#xff0c;由于其开源的特点&#xff0c;受到广大测试和开发同学的青睐。但是&#xff0c;在实际应用过程中&a…

数据结构 | 搜索和排序——搜索

目录 一、顺序搜索 二、分析顺序搜索算法 三、二分搜索 四、分析二分搜索算法 五、散列 5.1 散列函数 5.2 处理冲突 5.3 实现映射抽象数据类型 搜索是指从元素集合中找到某个特定元素的算法过程。搜索过程通常返回True或False&#xff0c;分别表示元素是否存在。有时&a…

LeetCode 热题 100 JavaScript--142. 环形链表 II

给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数…

HDFS架构刨析

HDFS架构刨析 概述HDFS架构图整体概述主角色&#xff1a;namenodefsimage内存元数据镜像文件edits log&#xff08;Journal&#xff09;编辑日志 从角色&#xff1a;datanode主角色辅助角色&#xff1a;secondarynamenode 重要特性主从架构分块存储机制副本机制namespace元数据…

快速搭建MQTT测试环境,手把手详细教程

文章目录 前言系统架构准备工具代理服务器客户端客户端 TEST-1客户端 TEST-2 验证消息传递订阅主题发布主题 前言 大家好&#xff0c;我是麦叔&#xff0c;之前有小伙伴建议出一期如何快速搭建一个MQTT协议的测试环境&#xff0c;这里要合理地使用现有的工具&#xff0c;其实很…

ubuntu18.04安装docker及docker基本命令的使用

官网安装步骤&#xff1a;https://docs.docker.com/desktop/install/ubuntu/ docker快速入门教程 Ubuntu-Docker安装和使用 docker官网 docker-hub仓库 1、常用指令 &#xff08;1&#xff09;镜像操作 # ############################# 以nginx为例 docker images docker p…

五分钟帮您理解Linux网络核心知识点——socket和epoll

关于linux网络相关的基础知识点&#xff0c;最热的两个就是socket和epoll&#xff0c;接下来我就用最简单的方式把他俩说清楚便于大家理解&#xff01; Socket Socket 是一种进程间通信的方法&#xff0c;它允许位于同一主机&#xff08;计算机&#xff09;或使用网络连接起来…

Android SystemServer中Service的创建和启动方式(基于Android13)

Android SystemServer创建和启动方式(基于Android13) SystemServer 简介 Android System Server是Android框架的核心组件&#xff0c;运行在system_server进程中&#xff0c;拥有system权限。它在Android系统中扮演重要角色&#xff0c;提供服务管理和通信。 system …

右键文件夹 ------- 打开 vscode的方法

1、右键vscode点击属性 2、这是地址栏&#xff0c;一会复制即可 3、新建一个txt文件,将这个复制进去 Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\*\shell\VSCode] "Open with Code" "Icon""D:\\Microsoft VS Code\\Code.exe"[HKE…

人到中年不得已,保温杯里泡枸杞--送程序员

目录 一&#xff1a;你现在身体的体能状况如何&#xff1f;你有身体焦虑吗&#xff1f; 二&#xff1a;如何保持规律性运动&#xff1f; 三&#xff1a;你有哪些健康生活的好习惯&#xff1f; 大厂裁员&#xff0c;称35岁以后体能下滑&#xff0c;无法继续高效率地完成工作&…

【数据结构OJ题】删除有序数组中的重复项

原题链接&#xff1a;https://leetcode.cn/problems/remove-duplicates-from-sorted-array/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 用双指针算法&#xff0c;定义两个变量src和dst&#xff0c;一开始让src和dst指向num[ ]数组的第一个元素&a…

Java注解详细介绍

Java注解详细介绍 基于注解(Annotation-based)的Java开发无疑是最新的开发趋势.[译者注: 这是05年的文章,在2014年,毫无疑问,多人合作的开发,使用注解变成很好的合作方式,相互之间的影响和耦合可以很低]. 基于注解的开发将Java开发人员从繁琐笨重的配置文件中解脱出来. Java 5…

hacksudo3 通关详解

环境配置 一开始桥接错网卡了 搞了半天 改回来就行了 信息收集 漏洞发现 扫个目录 大概看了一眼没什么有用的信息 然后对着login.php跑了一下弱口令 sqlmap 都没跑出来 那么利用点应该不在这 考虑到之前有过dirsearch字典太小扫不到东西的经历 换个gobuster扫一下 先看看g…

自然语言处理:长文本场景下的关键词抽取实践

NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等 专栏详细介绍:NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型…

HBase-读流程

创建连接同写流程。 &#xff08;1&#xff09;读取本地缓存中的Meta表信息&#xff1b;&#xff08;第一次启动客户端为空&#xff09; &#xff08;2&#xff09;向ZK发起读取Meta表所在位置的请求&#xff1b; &#xff08;3&#xff09;ZK正常返回Meta表所在位置&#x…

SpringBoot使用@Autowired将实现类注入到List或者Map集合中

前言 最近看到RuoYi-Vue-Plus翻译功能 Translation的翻译模块配置类TranslationConfig&#xff0c;其中有一个注入TranslationInterface翻译接口实现类的写法让我感到很新颖&#xff0c;但这种写法在Spring 3.0版本以后就已经支持注入List和Map&#xff0c;平时都没有注意到这…

自制免费 SQL 闯关自学网,代码开源!

大家好&#xff0c;我是鱼皮。 相信很多学编程的同学都学习过 SQL 吧&#xff1f;SQL 作为数据库查询语言&#xff0c;实在是太重要了&#xff0c;可以说是程序员、产品经理、数据分析同学的必备技能。 为了帮助大家自学 SQL&#xff0c;这段时间&#xff0c;我一个人做了个 …

ios_base::out和ios::out、ios_base::in和ios::in、ios_base::app和ios::app等之间有什么区别吗?

2023年8月2日&#xff0c;周三晚上 今天我看到了这样的两行代码&#xff1a; std::ofstream file("example.txt", std::ios_base::out);std::ofstream file("example.txt", std::ios::out);这让我产生了几个疑问&#xff1a; 为什么有时候用ios_base::o…

智慧城市规划新引擎:探秘数字孪生中的二维与三维GIS技术差异

智慧城市作为人类社会发展的新阶段&#xff0c;正日益引领着我们迈向数字化未来的时代。在智慧城市的建设过程中&#xff0c;地理信息系统&#xff08;GIS&#xff09;扮演着举足轻重的角色。而在GIS的发展中&#xff0c;二维和三维GIS作为两大核心技术&#xff0c;在城市规划与…