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


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

目录
相关文章
|
1天前
|
存储 算法 搜索推荐
C++|STL简介-string-vector基础运用
C++|STL简介-string-vector基础运用
|
3天前
|
设计模式 算法 C++
【C++】STL之迭代器介绍、原理、失效
【C++】STL之迭代器介绍、原理、失效
13 2
|
3天前
|
存储 C++ 容器
C++:STL - set & map
C++:STL - set & map
16 4
|
3天前
|
算法 安全 程序员
【C++】STL学习之旅——初识STL,认识string类
现在我正式开始学习STL,这让我期待好久了,一想到不用手撕链表,手搓堆栈,心里非常爽
16 0
|
3天前
|
存储 Serverless C++
【C++入门到精通】哈希 (STL) _ unordered_map _ unordered_set [ C++入门 ]
【C++入门到精通】哈希 (STL) _ unordered_map _ unordered_set [ C++入门 ]
10 1
|
3天前
|
存储 设计模式 算法
【C++/STL】stack和queue(容器适配器、优先队列、双端队列)
【C++/STL】stack和queue(容器适配器、优先队列、双端队列)
15 1
|
3天前
|
存储 编译器 C++
【C++/STL】list(常见接口、模拟实现、反向迭代器、)
【C++/STL】list(常见接口、模拟实现、反向迭代器、)
5 0
|
3天前
|
算法 C++ 容器
【C++/STL】vector(常见接口、模拟实现、迭代器失效)
【C++/STL】vector(常见接口、模拟实现、迭代器失效)
11 0
|
3天前
|
存储 算法 C++
详解C++中的STL(标准模板库)容器
【4月更文挑战第30天】C++ STL容器包括序列容器(如`vector`、`list`、`deque`、`forward_list`、`array`和`string`)、关联容器(如`set`、`multiset`、`map`和`multimap`)和容器适配器(如`stack`、`queue`和`priority_queue`)。它们为动态数组、链表、栈、队列、集合和映射等数据结构提供了高效实现。选择合适的容器类型可优化性能,满足不同编程需求。
|
3天前
|
存储 算法 程序员
C++从入门到精通:2.2.1标准库与STL容器算法深度解析
C++从入门到精通:2.2.1标准库与STL容器算法深度解析