vector容器

vector容器如何排序

在C++中,可以使用std::sort函数对std::vector进行排序。std::sort是定义在头文件中的函数,可以对容器中的元素进行升序或降序排序。

1. 升序排序

默认情况下,std::sort会对vector中的元素进行升序排序

#include 
#include 
#include 

int main() {
    std::vector<int> vec = {5, 2, 9, 1, 5, 6};

    // 升序排序
    std::sort(vec.begin(), vec.end());

    // 输出排序后的vector
    for (int i : vec) {
        std::cout << i << " ";
    }

    return 0;
}

输出:

1 2 5 5 6 9

2. 降序排序

如果要进行降序排序,可以使用std::greater作为std::sort的第三个参数。

#include 
#include 
#include 

int main() {
    std::vector<int> vec = {5, 2, 9, 1, 5, 6};

    // 降序排序
    std::sort(vec.begin(), vec.end(), std::greater<int>());

    // 输出排序后的vector
    for (int i : vec) {
        std::cout << i << " ";
    }

    return 0;
}

输出:

9 6 5 5 2 1

3. 自定义排序

你也可以通过自定义比较函数来实现更复杂的排序逻辑。

#include 
#include 
#include 

bool customCompare(int a, int b) {
    return a > b; // 降序排序
}

int main() {
    std::vector<int> vec = {5, 2, 9, 1, 5, 6};

    // 使用自定义比较函数进行排序
    std::sort(vec.begin(), vec.end(), customCompare);

    // 输出排序后的vector
    for (int i : vec) {
        std::cout << i << " ";
    }

    return 0;
}

输出:

9 6 5 5 2 1

4. 对自定义对象排序

如果vector中存储的是自定义对象,可以通过重载<运算符或提供自定义比较函数来排序。

#include 
#include 
#include 

struct Person {
    std::string name;
    int age;

    bool operator<(const Person& other) const {
        return age < other.age; // 按年龄升序排序
    }
};

int main() {
    std::vector<Person> people = {{"Alice", 25}, {"Bob", 20}, {"Charlie", 30}};

    // 按年龄升序排序
    std::sort(people.begin(), people.end());

    // 输出排序后的vector
    for (const auto& person : people) {
        std::cout << person.name << " (" << person.age << ")\n";
    }

    return 0;
}

输出:

Bob (20)
Alice (25)
Charlie (30)

总结

  • 使用std::sort可以对vector进行排序。
  • 默认是升序排序,可以通过std::greater实现降序排序。
  • 可以通过自定义比较函数或重载<运算符来实现更复杂的排序逻辑。

vector容器大小的计算

在C++中,二维的std::vector实际上是一个vectorvector,即std::vector>。要获取其大小(类似于二维数组的mn),可以通过以下方式:

  • m:表示外层vector的大小,即行数。
  • n:表示内层vector的大小,即列数(假设所有行的列数相同)。

示例代码

#include 
#include 

int main() {
    // 定义一个二维vector
    std::vector<std::vector<int>> vec = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
        {10, 11, 12}
    };

    // 获取行数(m)
    size_t m = vec.size();

    // 获取列数(n),假设所有行的列数相同
    size_t n = vec[0].size();

    // 输出结果
    std::cout << "行数 (m): " << m << std::endl;
    std::cout << "列数 (n): " << n << std::endl;

    return 0;
}

输出

行数 (m): 4
列数 (n): 3

注意事项

  1. 列数的获取

    • 代码中假设所有行的列数相同,因此直接使用vec[0].size()获取列数。
    • 如果二维vector的每一行列数可能不同(即不规则二维vector),则需要逐行检查列数。
  2. 不规则二维vector
    如果每一行的列数不同,可以使用循环遍历每一行,获取每一行的列数。

    for (size_t i = 0; i < vec.size(); ++i) {
        std::cout << "第 " << i << " 行的列数: " << vec[i].size() << std::endl;
    }
    
  3. 空二维vector
    如果二维vector为空(即vec.size() == 0),则不能直接访问vec[0].size(),否则会导致未定义行为。需要先检查外层vector是否为空。

    if (!vec.empty()) {
        size_t n = vec[0].size();
        std::cout << "列数 (n): " << n << std::endl;
    } else {
        std::cout << "二维vector为空,无法获取列数。" << std::endl;
    }
    

总结

  • 使用vec.size()获取行数(m)。
  • 使用vec[0].size()获取列数(n),前提是二维vector不为空且所有行的列数相同。
  • 对于不规则二维vector,需要逐行检查列数。
  • 注意处理空二维vector的情况。

pair键值对

在C++中,std::pair 是一个模板类,用于将两个值组合成一个单一的对象。它通常用于需要存储一对值的情况,例如键值对、坐标点等。以下是关于 std::pair 的详细使用方法和注意事项。

1. std::pair 的基本用法

定义和初始化

std::pair 的定义如下:

template <class T1, class T2>
struct pair;
  • T1 是第一个值的类型。
  • T2 是第二个值的类型。

可以通过以下方式定义和初始化 std::pair

#include  // std::pair 的头文件
#include 

int main() {
    // 方法 1:直接初始化
    std::pair<int, std::string> p1(1, "Alice");

    // 方法 2:使用 make_pair 函数
    auto p2 = std::make_pair(2, "Bob");

    // 方法 3:默认构造函数 + 赋值
    std::pair<int, std::string> p3;
    p3.first = 3;
    p3.second = "Charlie";

    // 输出
    std::cout << "p1: (" << p1.first << ", " << p1.second << ")\n";
    std::cout << "p2: (" << p2.first << ", " << p2.second << ")\n";
    std::cout << "p3: (" << p3.first << ", " << p3.second << ")\n";

    return 0;
}

输出:

p1: (1, Alice)
p2: (2, Bob)
p3: (3, Charlie)

2. 访问 std::pair 的成员

std::pair 有两个公有成员:

  • first:第一个值。
  • second:第二个值。

可以通过 . 运算符直接访问:

std::pair<int, std::string> p(1, "Alice");
std::cout << "First: " << p.first << ", Second: " << p.second << std::endl;

3. std::pair 的比较

std::pair 支持比较操作(==, !=, <, <=, >, >=)。比较规则是:

  1. 先比较 first,如果 first 不相等,则根据 first 的大小决定结果。
  2. 如果 first 相等,则比较 second

示例:

std::pair<int, int> p1(1, 2);
std::pair<int, int> p2(1, 3);
std::pair<int, int> p3(2, 1);

std::cout << (p1 < p2) << std::endl;  // true,因为 first 相等,second 2 < 3
std::cout << (p1 < p3) << std::endl;  // true,因为 first 1 < 2

4. std::pair 的赋值和拷贝

std::pair 支持赋值和拷贝操作:

std::pair<int, std::string> p1(1, "Alice");
std::pair<int, std::string> p2 = p1; // 拷贝
std::pair<int, std::string> p3;
p3 = p1; // 赋值

5. std::pair 的常见用途

(1)作为返回值

std::pair 常用于函数返回多个值:

std::pair<int, int> minMax(const std::vector<int>& nums) {
    int minVal = nums[0], maxVal = nums[0];
    for (int num : nums) {
        if (num < minVal) minVal = num;
        if (num > maxVal) maxVal = num;
    }
    return {minVal, maxVal};
}
(2)在容器中使用

std::pair 常用于 std::mapstd::unordered_map 的键值对:

std::map<std::string, int> wordCount;
wordCount["apple"] = 5;
wordCount["banana"] = 3;

for (const auto& entry : wordCount) {
    std::cout << entry.first << ": " << entry.second << std::endl;
}
(3)存储坐标或区间

std::pair 可以用于存储二维坐标或区间:

std::pair<int, int> point(3, 4); // 表示坐标 (3, 4)
std::pair<int, int> interval(1, 5); // 表示区间 [1, 5]

6. 注意事项

(1)类型匹配

std::pair 的两个值的类型是固定的,不能动态改变。如果需要存储不同类型的值,可以使用 std::variantstd::any

(2)性能

std::pair 是一个轻量级的结构,拷贝和赋值操作的开销较小。但如果存储的是大型对象(如字符串或容器),可能会影响性能。

7. 总结

  • std::pair 是一个简单而强大的工具,用于将两个值组合在一起。
  • 它支持比较、赋值、拷贝等操作。
  • 常用于函数返回值、容器中的键值对、坐标或区间等场景。
  • 注意类型匹配、性能问题和默认构造函数的限制。
  • 在 C++17 中,可以使用结构化绑定或 std::tie 简化代码。

vector与pair键值对结合

在 C++ 中,std::vector> 是一种常见的容器类型,用于存储多个键值对(pair)。每个元素是一个 std::pair,其中包含两个 int 类型的值。以下是对这种容器的详细操作说明。

1. 定义和初始化

(1)直接初始化

可以在定义时直接初始化 std::vector>

#include 
#include  // std::pair 的头文件

int main() {
    // 直接初始化
    std::vector<std::pair<int, int>> vec = {
        {1, 10},
        {2, 20},
        {3, 30}
    };

    return 0;
}
(2)默认初始化

可以先定义一个空的 vector,然后通过 push_backemplace_back 添加元素:

std::vector<std::pair<int, int>> vec;
vec.push_back({1, 10});
vec.push_back({2, 20});
vec.push_back({3, 30});
(3)使用 emplace_back

emplace_back 可以直接在容器中构造元素,避免额外的拷贝或移动操作

std::vector<std::pair<int, int>> vec;
vec.emplace_back(1, 10); // 直接构造 pair
vec.emplace_back(2, 20);
vec.emplace_back(3, 30);

2. 访问元素

(1)通过索引访问

可以使用 []at() 访问 vector 中的元素:

std::vector<std::pair<int, int>> vec = {
    {1, 10},
    {2, 20},
    {3, 30}
};

// 使用 [] 访问
std::cout << "First element: (" << vec[0].first << ", " << vec[0].second << ")\n";

// 使用 at() 访问
std::cout << "Second element: (" << vec.at(1).first << ", " << vec.at(1).second << ")\n";
(2)遍历容器

可以使用范围 for 循环或迭代器遍历 vector

// 范围 for 循环
for (const auto& p : vec) {
    std::cout << "(" << p.first << ", " << p.second << ")\n";
}

// 使用迭代器
for (auto it = vec.begin(); it != vec.end(); ++it) {
    std::cout << "(" << it->first << ", " << it->second << ")\n";
}

3. 修改元素

(1)修改单个元素

可以通过索引或迭代器修改 vector 中的元素:

vec[0] = {4, 40}; // 修改第一个元素
vec.at(1) = {5, 50}; // 修改第二个元素

// 使用迭代器修改
auto it = vec.begin() + 2;
it->first = 6;
it->second = 60;
(2)添加元素

可以使用 push_backemplace_back 添加元素:

vec.push_back({7, 70}); // 添加一个 pair
vec.emplace_back(8, 80); // 直接构造并添加
(3)删除元素

可以使用 erase 删除元素:

vec.erase(vec.begin() + 1); // 删除第二个元素

4. 排序

std::vector> 可以使用 std::sort 进行排序。默认情况下,std::sort 会按照 pair 的第一个值(first)升序排序。

(1)默认排序
#include  // std::sort 的头文件

std::vector<std::pair<int, int>> vec = {
    {3, 30},
    {1, 10},
    {2, 20}
};

// 默认按 first 升序排序
std::sort(vec.begin(), vec.end());

// 输出排序结果
for (const auto& p : vec) {
    std::cout << "(" << p.first << ", " << p.second << ")\n";
}

输出:

(1, 10)
(2, 20)
(3, 30)
(2)自定义排序

可以通过传递自定义比较函数来实现按 second 排序或其他规则:

// 按 second 升序排序
std::sort(vec.begin(), vec.end(), [](const std::pair<int, int>& a, const std::pair<int, int>& b) {
    return a.second < b.second;
});

5. 查找元素

可以使用 std::find_ifstd::lower_bound 查找满足条件的元素。

(1)使用 std::find_if
int target = 20;
auto it = std::find_if(vec.begin(), vec.end(), [target](const std::pair<int, int>& p) {
    return p.second == target;
});

if (it != vec.end()) {
    std::cout << "Found: (" << it->first << ", " << it->second << ")\n";
} else {
    std::cout << "Not found\n";
}
(2)使用 std::lower_bound

std::lower_bound 适用于已排序的容器:

int target = 20;
auto it = std::lower_bound(vec.begin(), vec.end(), std::make_pair(target, 0));

if (it != vec.end() && it->first == target) {
    std::cout << "Found: (" << it->first << ", " << it->second << ")\n";
} else {
    std::cout << "Not found\n";
}

6. 注意事项

(1)性能
  • std::vector 的插入和删除操作在尾部是高效的(O(1)),但在中间或头部是低效的(O(n))。
  • 如果需要频繁插入和删除,可以考虑使用 std::liststd::deque
(2)内存管理
  • std::vector 会自动管理内存,但当元素数量增加时,可能会导致重新分配内存和拷贝数据。
  • 可以使用 reserve 预分配内存以避免频繁重新分配。
(3)空容器
  • 在访问元素之前,应检查容器是否为空,以避免未定义行为。

7. 示例代码

以下是一个完整的示例,展示如何使用 std::vector>

#include 
#include 
#include 
#include 

int main() {
    // 定义并初始化
    std::vector<std::pair<int, int>> vec = {
        {3, 30},
        {1, 10},
        {2, 20}
    };

    // 添加元素
    vec.emplace_back(4, 40);

    // 排序
    std::sort(vec.begin(), vec.end());

    // 遍历
    for (const auto& p : vec) {
        std::cout << "(" << p.first << ", " << p.second << ")\n";
    }

    // 查找
    int target = 20;
    auto it = std::find_if(vec.begin(), vec.end(), [target](const std::pair<int, int>& p) {
        return p.second == target;
    });

    if (it != vec.end()) {
        std::cout << "Found: (" << it->first << ", " << it->second << ")\n";
    } else {
        std::cout << "Not found\n";
    }

    return 0;
}

输出:

(1, 10)
(2, 20)
(3, 30)
(4, 40)
Found: (2, 20)

总结

  • std::vector> 是一种灵活的容器,适合存储键值对。
  • 支持初始化、访问、修改、排序、查找等操作。
  • 注意性能和内存管理问题,合理选择容器和算法。

你可能感兴趣的:(C++基础语法,c++)