c++之STL详解(二)

简介: c++之STL详解(二)

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. 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 等,来接收自定义函数作为参数。


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

目录
相关文章
|
2月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
112 10
|
4天前
|
算法 C语言 C++
【c++丨STL】list的使用
本文介绍了STL容器`list`的使用方法及其主要功能。`list`是一种双向链表结构,适用于频繁的插入和删除操作。文章详细讲解了`list`的构造函数、析构函数、赋值重载、迭代器、容量接口、元素访问接口、增删查改操作以及一些特有的操作接口如`splice`、`remove_if`、`unique`、`merge`、`sort`和`reverse`。通过示例代码,读者可以更好地理解如何使用这些接口。最后,作者总结了`list`的特点和适用场景,并预告了后续关于`list`模拟实现的文章。
20 7
|
21天前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
47 4
|
23天前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
48 5
|
23天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
36 2
|
28天前
|
存储 算法 Linux
【c++】STL简介
本文介绍了C++标准模板库(STL)的基本概念、组成部分及学习方法,强调了STL在提高编程效率和代码复用性方面的重要性。文章详细解析了STL的六大组件:容器、算法、迭代器、仿函数、配接器和空间配置器,并提出了学习STL的三个层次,旨在帮助读者深入理解和掌握STL。
46 0
|
7天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
18 0
|
2月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
58 2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
|
2月前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
79 5
|
2月前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
70 1