【C++修行之道】STL(初识pair、vector)

简介: 【C++修行之道】STL(初识pair、vector)



一、pair

1.1pair的定义和结构

在C++中,pair是一个模板类,用于一对值的组合。它位于<utility>头文件中。pair类的定义如下:

template<class T1,class T2>
struct pair {
  T1 fiest;//第一个值
  T2 second;//第二个值
  //构造函数
  pair();
  pair(const T1& x, const T2& y);
  //比较运算符重载
  bool operator ==(const pair& rhs)const;
  bool operator !=(const pair& rhs)const;
  //其他成员函数和特性
  //...
};
  • pair类模板有两个模板参数,T1和T2,分别表示第一个值和第二个值的类型。
  • pair类有两个成员变量,first和second,分别表示第一个值和第二个值。
  • pair类还有一些成员函数和特性,例如默认构造函数、带参数的构造函数、比较运算符重载等。
  • 使用pair类,你可以方便地将两个值组合在一起,并进行传递、存储和操作。

例如,可以将两个整数组合在一起作为函数的返回值,或者将一对值存储在容器中

下面是一些使用pair的示例:

int main()
{
  pair<int, double>p1(1, 3.14);
  pair<char, string>p2('a', "hello");
  cout << p1.first << ", " << p1.second << endl;
  cout << p2.first << ", " << p2.second << endl;
  
}

以上代码创建了两个pair对象,分别包含不同类型的值。然后,通过访问fisrt和second成员变量,输出了这些值。

1.2pair的嵌套

pair可以进行嵌套,也就是说可以将一个pair对象做为另一个pair对象的成员。通过嵌套pair,你可以方便组合多个值,并形成更复杂的数据结构。

例如,你可以创建一个三维坐标系的点,其中第一个维度由第一个整数表示,第2,3个维度由一个pair表示。

下面是一个示例代码,演示了如何嵌套使用pair:

#include <iostream>   
#include <utility>  
  
using namespace std; 
  
int main()  
{  
    // 创建一个包含两个整数的pair对象p1,初始化为(1, 2)  
    pair<int, int> p1(1, 2);  
      
    // 创建一个pair对象p2,其第一个元素是整数3,第二个元素是另一个pair<int, int>对象,初始化为(4, 5)  
    pair<int, pair<int, int>> p2(3, make_pair(4, 5));  
      
    // 创建一个pair对象p3,其两个元素都是pair<int, int>对象,分别初始化为(6, 7)和(8, 9)  
    pair<pair<int, int>, pair<int, int>> p3(make_pair(6, 7), make_pair(8, 9));  
  
    // 打印p1的第一个和第二个元素  
    cout << p1.first << ", " << p1.second << endl;  
      
    // 打印p2的第一个元素,以及p2的第二个元素的第一个和第二个子元素  
    cout << p2.first << ", " << p2.second.first << ", " << p2.second.second << endl;  
      
    // 打印p3的第一个元素的第一个和第二个子元素,以及p3的第二个元素的第一个和第二个子元素  
    cout << p3.first.first << ", " << p3.first.second << ", " << p3.second.first << ", " << p3.second.second << endl;  
  
    return 0; // 程序正常退出  
}

1.3pair自带排序规则

pair自带的排序规则是按照first成员进行升序排序。

如果first成员相等,则按照second成员进行升序排序。

这意味着当你使用标准库中的排序算法(如std::sort)对包含pair对象的容器进行排序时,会根据pair对象的first成员进行排序。

下面是一个示例代码,演示了如何使用pair进行排序:

#include<iostream>
#include<utility>
#include<vector>
#include<algorithm>
int main()
{
  vector<pair<int, int>>vec;
  vec.push_back(make_pair(3, 2));
  vec.push_back(make_pair(1, 4));
  vec.push_back(make_pair(2, 1));
  sort(vec.begin(), vec.end());
  for (const auto& p : vec) {
    cout << p.first << ", " << p.second << endl;
  }
  return 0;
}

1.4代码示例

#include<iostream>
#include<utility>
#include<vector>
//定义一个结构体,表示一个人的信息
struct Person {
  string name;
  int age;
};
int main()
{
  //创建一个存储Person对象的向量
  vector<Person> people;
  //添加一些Person对象到向量中
  people.push_back({ "Alice",25 });
  people.push_back({ "Bod",30 });
  people.push_back({ "Charlie",20 });
  //创建一个存储pair的向量,每个pair包含一个Person对象和一个评分
  vector<pair<Person, int>>scores;
  //添加一些pair到向量中
  scores.push_back({ people[0],90 });
  scores.push_back({ people[1],85 });
  scores.push_back({ people[2],95 });
  //遍历pair向量,并输出每个人的姓名,年龄和评分
  for (const auto& pair : scores) {
    cout << "Name: " << pair.first.name << endl;
    cout << "Age: " << pair.first.age << endl;
    cout << "Score: " << pair.second << endl;
    cout << endl;
  }
  return 0;
}

二、vector

2.1vector的定义和特性

在C++中,vector是一个动态数组容器可以存储一系列相同类型的元素.

它是标准库<vector>中定义的模板类。

vector为可变长数组(动态数组),定义的vector数组可以随时添加数值和删除元素。


vector的定义和结构非常简单,它由以下几个重要的部分组成:

模板类声明:vector是一个模板类,因此在使用之前需要包含头文件<vector>。声明一个vector对象的通用语法如下:

std::vector<T> vec;

这里的T是要存储在vector中的元素类型。

  • 容器大小:vector是一个动态数组,可以根据需要自动调整大小。 它会根据元素的数量动态分配内存空间。
  • 容器大小管理:可以使用size()函数获取vector中元素的数量,使用empty()函数检查vector是否为空,还可以使用resize()函数调整ector的大小。
  • 迭代器: vector提供了迭代器,可以用于遍历容器中的元素。可以使用begin()函数获取指向第一个元素的迭代器,使用end()函数获取指向最后一个元素之后位置的迭代器。

在局部作用域内(例如局部函数内部),创建vector对象时,其内部数组是在堆空间中分配的。

通常,在局部作用域内直接声明的数组是分配在栈空间上的。由于栈空间相对有限,如果声明了过大的数组,很容易引发栈溢出错误。

因此,在局部作用域内,我们应避免声明长度过大的数组,但可以选择使用vector。vector能够动态地在堆空间中管理内存,从而支持存储大量元素而不会导致栈溢出。这使得vector成为处理大量数据的局部变量的理想选择。

2.2vector的初始化

一维初始化:

vector<int> a; //定义了一个名为a的一维数组,数组存储int类型数据
vector<double> b;//定义了一个名为b的一维数组,数组存储double类型数据
// 定义结构体 Node  
struct Node {  
    int id;  
    std::string name;
}
vector<Node> c;//定义了一个名为c的一维数组,数组存储结构体类型数据,node是结构体类型

指定长度和初始值的初始化

vector<int> v(n);// 定义一个长度为n的数组,初始值默认为0,下标范围[0, n - 1]
vector<int> v(n, 1);// v[0] 到 v[n - 1]所有的元素初始值均为1
//注意:指定数组长度之后(指定长度后的数组就相当于正常的数组了)

2.3vector的常用函数

push_back():将元素添加到vector的末尾

void push back(const T&value);

pop_back():删除vector末尾的元素(保证vector非空)

void pop_back();

begin()和 end(): 返回指向vector第一个元素和最后一个元素之后位置的迭代器

iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;

示例:

std::vector<int> vec = {10,20,30};
for (auto it = vec.begin(); it != vec.end(); ++it) {
  std::cout << *it << " ";
}

2.4vector排序去重

排序:

要对vector进行排序,可以使用标准库中的std::sort函数。

该函数位于头文件<algorithm>中。

#include <algorithm>
std::vector<T> vec = {...};
std::sort(vec.begin(),vec.end());

这里的T是vector中元素的类型。std::sort函数接受两个迭代器参数,表示要排序的范围。

vec.begin()返回指向vector第一个元素的迭代器。

vec.end()返回指向最后一个元素之后位置的迭代器

去重:

要去除vector中的重复元素,可以使用std:unique函数。该函数位于头文件<algorithm>中

#include <algorithm>
std::vector<T> vec = [...};
std::sort(vec.begin(),vec.end()); 
auto last = std::unique(vec.begin(), vec.end());
vec.erase(last,vec.end());

首先,需要对vector进行排序,以便相同的元素相邻。然后,std:unique函数将重复的元素移动到vector的末尾,并返回一个指向重复元素的迭代器。最后,可以使用vec.erase函数将重复元素从vector中删除。

示例:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
  vector<int>vec = { 2,1,3,2,4,1,5,4 };
  sort(vec.begin(), vec.end());
  auto last = unique(vec.begin(), vec.end());
  vec.erase(last, vec.end());
  for (const auto&num : vec) {
    cout << num << " ";
  }
  cout << endl;
  return 0;
}

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
  //创建一个空的 std::vector 对象
  std::vector<int> numbers;
  //向向量中添加元素
  numbers.push_back(5);
  numbers.push_back(2);
  numbers.push_back(8);
  numbers.push_back(5);
  numbers.push_back(1);
  numbers.push_back(2);
  numbers.push_back(9);
  numbers.push_back(8);
  
  //打印向量中的元素
  cout << "原始向量中的元素: ";
  for (const auto& number : numbers) {
    cout << number << " ";
  }
  cout << endl;
  //对向量进行排序
  sort(numbers.begin(), numbers.end());
  //打印排序后的向量
  cout << "排序后的向量: ";
  for (const auto& number : numbers) {
    cout << number << " ";
  }
  cout << endl;
  //去除重复元素
  numbers.erase(std::unique(numbers.begin(), numbers.end()), numbers.end());
  //打印去重个后的向量
  cout << "去重后的向量: ";
  for (const auto& number : numbers) {
    cout << number << " ";
  }
  cout << endl;
  //向向量中插入元素
  numbers.insert(numbers.begin() + 2, 3);
  //打印插入元素后的向量
  cout << "插入元素后的向量: ";
  for (const auto& number : numbers) {
    cout << number << endl;
  }
  cout << endl;
  //删除向量中的某个元素
  numbers.erase(numbers.begin() + 4);
  //打印删除元素后的向量
  cout << "删除元素后的向量: ";
  for (const auto& number : numbers) {
    cout << number << endl;
  }
  cout << endl;
  //检查向量是否为空
  if (numbers.empty()) {
    cout << "向量为空" << endl;
  }
  else {
    cout << "向量不为空" << endl;
  }
  //获取向量的大小
  cout << "向量的大小: " << numbers.size() << endl;
  //清空向量
  numbers.clear();
  //检查向量是否为空
  if (numbers.empty()) {
    cout << "向量为空" << endl;
  }
  else {
    cout << "向量不为空" << endl;
  }
  return 0;
}

今天就先到这了!!!

看到这里了还不给博主扣个:

⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!

有问题可以评论或者私信呢秒回哦。

相关文章
|
17天前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
44 4
|
18天前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
44 5
|
18天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
29 2
|
24天前
|
存储 算法 Linux
【c++】STL简介
本文介绍了C++标准模板库(STL)的基本概念、组成部分及学习方法,强调了STL在提高编程效率和代码复用性方面的重要性。文章详细解析了STL的六大组件:容器、算法、迭代器、仿函数、配接器和空间配置器,并提出了学习STL的三个层次,旨在帮助读者深入理解和掌握STL。
40 0
|
3天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
12 0
|
2月前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
74 5
|
2月前
|
存储 C++ 索引
【C++打怪之路Lv9】-- vector
【C++打怪之路Lv9】-- vector
25 1
|
2月前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
67 1
|
24天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
59 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
62 4