为了账号安全,请及时绑定邮箱和手机立即绑定

STL容器教程:新手入门详解

标签:
C++
概述

本文详细介绍了STL容器教程,涵盖STL容器的基本概念、作用与优点,及各种容器如vectorlistqueuestackmap的具体使用方法。文章提供了丰富的示例代码,帮助读者理解如何初始化、插入、删除和遍历这些容器。通过学习本文,读者可以全面掌握STL容器的使用技巧和应用场景。

STL容器简介

什么是STL容器

STL(Standard Template Library,标准模板库)是C++标准库的一部分,提供了一系列容器类,这些容器可以用来存储、管理和操作各种数据。STL容器设计的主要目标是提供一个通用接口,使得不同类型的容器可以使用相同的操作方法。常见的STL容器包括向量(vector)、链表(list)、队列(queue)、堆栈(stack)和映射(map)等。

STL容器的作用与优点

STL容器在C++编程中扮演着重要的角色,其主要作用和优点如下:

  1. 方便的数据存储与操作:STL容器为不同的数据存储需求提供了多种选项,可以根据具体需要选择合适的容器类型。例如,vector适用于动态数组的扩展,list适合频繁插入和删除操作。
  2. 统一的接口:通过使用模板,STL容器提供了一组统一的成员函数,如push_backpop_backpush_frontpop_frontinserterase等,这使得编程更加直观和简洁。
  3. 高效的数据操作:STL容器在实现上做了优化,能够高效地完成插入、删除、查找等操作。例如,vectordeque使用连续的内存空间,允许快速访问,而listforward_list使用链表结构,便于插入和删除。
  4. 方便的迭代操作:STL容器支持迭代器,通过迭代器可以遍历容器中的所有元素,方便进行各种操作。
  5. 简化代码:通过使用STL容器,可以避免手动编写复杂的数据存储和管理代码,从而简化编程过程。

示例代码

#include <iostream>
#include <vector>
#include <list>

int main() {
    // 使用vector
    std::vector<int> vec;
    vec.push_back(1);    // 在末尾添加元素
    vec.push_back(2);
    vec.push_back(3);

    // 使用list
    std::list<int> lst;
    lst.push_back(1);    // 在末尾添加元素
    lst.push_back(2);
    lst.push_back(3);

    std::cout << "Vector elements: ";
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << "\nList elements: ";
    for (int i : lst) {
        std::cout << i << " ";
    }

    return 0;
}
常用STL容器介绍

向量(vector)

vector是C++中一种动态数组,其内部使用连续的内存空间存储元素。vector在操作上提供了高效的随机访问和修改操作,适用于需要频繁访问元素位置的情况。

特点

  • 动态扩展vector在需要时可以自动扩展其容量。
  • 高效访问:通过索引访问元素非常高效。
  • 内存连续vector内部使用连续的内存空间存储元素,支持快速访问。

示例代码

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec;

    vec.push_back(1);    // 在末尾添加元素
    vec.push_back(2);
    vec.push_back(3);

    vec[0] = 4;          // 修改第一个元素

    std::cout << "Vector elements: ";
    for (int i : vec) {
        std::cout << i << " ";
    }

    return 0;
}

链表(list)

list是一种双链表的实现,支持高效的插入和删除操作。list使用链表结构存储元素,因此在内存中不连续,但可以在任意位置进行插入和删除操作。

特点

  • 高效插入和删除:在链表中的任意位置插入或删除一个元素都非常高效。
  • 内存不连续list内部使用链表结构存储元素,支持快速插入和删除。

示例代码

#include <iostream>
#include <list>

int main() {
    std::list<int> lst;

    lst.push_back(1);    // 在末尾添加元素
    lst.push_back(2);
    lst.push_back(3);

    lst.insert(lst.begin(), 0);    // 在开始位置插入元素

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

    std::cout << "List elements: ";
    for (int i : lst) {
        std::cout << i << " ";
    }

    return 0;
}

队列(queue)

queue是一种先进先出(FIFO)的数据结构,适用于需要按顺序处理元素的场景。queue通常用于模拟队列的行为,如打印队列、服务队列等。

特点

  • 先进先出:元素先进入队列,后被移除。
  • 有限操作:通常只提供pushpopfrontback等基本操作。

示例代码

#include <iostream>
#include <queue>

int main() {
    std::queue<int> que;

    que.push(1);    // 在末尾添加元素
    que.push(2);
    que.push(3);

    std::cout << "Queue elements: ";
    while (!que.empty()) {
        std::cout << que.front() << " ";
        que.pop();
    }

    return 0;
}

堆栈(stack)

stack是一种后进先出(LIFO)的数据结构,适用于需要按逆序处理元素的场景。stack通常用于模拟堆栈的行为,如函数调用栈、撤销操作等。

特点

  • 后进先出:元素后进入堆栈,先被移除。
  • 有限操作:通常只提供pushpoptop等基本操作。

示例代码

#include <iostream>
#include <stack>

int main() {
    std::stack<int> stk;

    stk.push(1);    // 在末尾添加元素
    stk.push(2);
    stk.push(3);

    while (!stk.empty()) {
        std::cout << stk.top() << " ";    // 输出堆栈顶部元素
        stk.pop();                        // 移除堆栈顶部元素
    }

    return 0;
}

映射(map)

map是一种关联容器,使用键值对存储数据,其中每个键都是唯一的。map通常用于模拟字典或哈希表的行为,适用于需要快速查找和操作键值对的场景。

特点

  • 键值对存储:每个键值对由键和对应的值组成。
  • 键唯一:每个键在map中都是唯一的,不允许重复。
  • 有序存储map中的键是有序的,可以按键的顺序遍历。

初始化容器

#include <iostream>
#include <map>

int main() {
    std::map<int, std::string> mp;

    mp[1] = "One";    // 添加键值对
    mp[2] = "Two";
    mp[3] = "Three";

    std::cout << "Map elements: ";
    for (const auto& pair : mp) {
        std::cout << "Key: " << pair.first << " Value: " << pair.second << " ";
    }

    return 0;
}

插入与删除元素

#include <iostream>
#include <map>

int main() {
    std::map<int, std::string> mp;

    mp[1] = "One";    // 插入键值对
    mp[2] = "Two";
    mp[3] = "Three";

    mp.erase(2);      // 删除键为2的键值对

    return 0;
}

遍历容器

#include <iostream>
#include <map>

int main() {
    std::map<int, std::string> mp = {{1, "One"}, {2, "Two"}, {3, "Three"}};

    for (const auto& pair : mp) {
        std::cout << "Key: " << pair.first << " Value: " << pair.second << " ";
    }

    return 0;
}

修改元素

#include <iostream>
#include <map>

int main() {
    std::map<int, std::string> mp = {{1, "One"}, {2, "Two"}, {3, "Three"}};

    mp[2] = "Two Modified";  // 修改键为2的值

    for (const auto& pair : mp) {
        std::cout << "Key: " << pair.first << " Value: " << pair.second << " ";
    }

    return 0;
}
STL容器的基本操作

初始化容器

初始化容器是使用STL容器的第一步,通常可以通过构造函数或初始化列表来完成。

示例代码

#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>

int main() {
    // 初始化vector
    std::vector<int> vec = {1, 2, 3};

    // 初始化list
    std::list<int> lst = {1, 2, 3};

    // 初始化queue
    std::queue<int> que;
    que.push(1);
    que.push(2);
    que.push(3);

    // 初始化stack
    std::stack<int> stk;
    stk.push(1);
    stk.push(2);
    stk.push(3);

    // 初始化map
    std::map<int, std::string> mp = {{1, "One"}, {2, "Two"}, {3, "Three"}};

    std::cout << "Vector elements: ";
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << "\nList elements: ";
    for (int i : lst) {
        std::cout << i << " ";
    }
    std::cout << "\nQueue elements: ";
    while (!que.empty()) {
        std::cout << que.front() << " ";
        que.pop();
    }
    std::cout << "\nStack elements: ";
    while (!stk.empty()) {
        std::cout << stk.top() << " ";
        stk.pop();
    }
    std::cout << "\nMap elements: ";
    for (const auto& pair : mp) {
        std::cout << "Key: " << pair.first << " Value: " << pair.second << " ";
    }

    return 0;
}

插入与删除元素

插入和删除元素是使用STL容器的基本操作,可以通过各种方法实现。

示例代码

#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>

int main() {
    // vector
    std::vector<int> vec = {1, 2, 3};
    vec.insert(vec.begin() + 1, 4);  // 在第二个位置插入元素4
    vec.erase(vec.begin() + 1);      // 删除第二个元素

    // list
    std::list<int> lst = {1, 2, 3};
    lst.insert(lst.begin(), 0);      // 在开始位置插入元素0
    lst.erase(lst.begin() + 2);      // 删除第三个元素

    // queue
    std::queue<int> que = {1, 2, 3};
    que.push(4);                     // 在末尾添加元素4
    que.pop();                       // 移除队首元素

    // stack
    std::stack<int> stk = {1, 2, 3};
    stk.push(4);                     // 在末尾添加元素4
    stk.pop();                       // 移除堆栈顶部元素

    // map
    std::map<int, std::string> mp = {{1, "One"}, {2, "Two"}, {3, "Three"}};
    mp.insert({4, "Four"});          // 插入新的键值对
    mp.erase(2);                     // 删除键为2的键值对

    return 0;
}

遍历容器

遍历容器通常使用迭代器或者范围for语句实现,可以方便地访问容器中的所有元素。

示例代码

#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>

int main() {
    // vector
    std::vector<int> vec = {1, 2, 3, 4};
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << "\n";

    // list
    std::list<int> lst = {1, 2, 3, 4};
    for (int i : lst) {
        std::cout << i << " ";
    }
    std::cout << "\n";

    // queue
    std::queue<int> que = {1, 2, 3, 4};
    while (!que.empty()) {
        std::cout << que.front() << " ";
        que.pop();
    }
    std::cout << "\n";

    // stack
    std::stack<int> stk = {1, 2, 3, 4};
    while (!stk.empty()) {
        std::cout << stk.top() << " ";
        stk.pop();
    }
    std::cout << "\n";

    // map
    std::map<int, std::string> mp = {{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}};
    for (const auto& pair : mp) {
        std::cout << "Key: " << pair.first << " Value: " << pair.second << " ";
    }
    std::cout << "\n";

    return 0;
}

修改元素

修改容器中的元素通常通过索引或者迭代器完成。

示例代码

#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>

int main() {
    // vector
    std::vector<int> vec = {1, 2, 3, 4};
    vec[0] = 0;  // 修改第一个元素
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << "\n";

    // list
    std::list<int> lst = {1, 2, 3, 4};
    auto iter = lst.begin();
    ++iter;
    *iter = 0;  // 修改第二个元素
    for (int i : lst) {
        std::cout << i << " ";
    }
    std::cout << "\n";

    // queue
    std::queue<int> que = {1, 2, 3, 4};
    que.push(5);
    que.front() = 0;  // 修改队首元素
    while (!que.empty()) {
        std::cout << que.front() << " ";
        que.pop();
    }
    std::cout << "\n";

    // stack
    std::stack<int> stk = {1, 2, 3, 4};
    stk.push(5);
    stk.top() = 0;  // 修改堆栈顶部元素
    while (!stk.empty()) {
        std::cout << stk.top() << " ";
        stk.pop();
    }
    std::cout << "\n";

    // map
    std::map<int, std::string> mp = {{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}};
    mp[1] = "Zero";  // 修改键为1的值
    for (const auto& pair : mp) {
        std::cout << "Key: " << pair.first << " Value: " << pair.second << " ";
    }
    std::cout << "\n";

    return 0;
}
容器之间转换

如何将一个容器转换为其他类型

容器之间转换通常需要将一个容器中的元素复制到另一个容器中。例如,可以将vector中的元素复制到list中,或者将list中的元素复制到vector中。

示例代码

#include <iostream>
#include <vector>
#include <list>

int main() {
    // 将vector转换为list
    std::vector<int> vec = {1, 2, 3, 4};
    std::list<int> lst(vec.begin(), vec.end());

    // 将list转换为vector
    std::list<int> lst2 = {5, 6, 7, 8};
    std::vector<int> vec2(lst2.begin(), lst2.end());

    std::cout << "List elements: ";
    for (int i : lst) {
        std::cout << i << " ";
    }
    std::cout << "\nVector elements: ";
    for (int i : vec2) {
        std::cout << i << " ";
    }

    return 0;
}

使用适配器(如deque, set)

适配器可以将一个容器适配为另一种类型。例如,可以将vector适配为deque,或将list适配为set

示例代码

#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <set>

int main() {
    // 将vector适配为deque
    std::vector<int> vec = {1, 2, 3, 4};
    std::deque<int> deq(vec.begin(), vec.end());

    // 将list适配为set
    std::list<int> lst = {4, 3, 2, 1};
    std::set<int> st(lst.begin(), lst.end());

    std::cout << "Deque elements: ";
    for (int i : deq) {
        std::cout << i << " ";
    }
    std::cout << "\nSet elements: ";
    for (int i : st) {
        std::cout << i << " ";
    }

    return 0;
}
解决问题示例

使用容器解决实际问题的示例代码

下面是一个使用vectormap来解决实际问题的例子:统计字符串中每个字符出现的次数。

示例代码

#include <iostream>
#include <vector>
#include <map>

int main() {
    std::string str = "hello world";
    std::map<char, int> char_count;

    for (char c : str) {
        char_count[c]++;
    }

    std::cout << "Character counts: ";
    for (const auto& pair : char_count) {
        std::cout << "Char: " << pair.first << " Count: " << pair.second << " ";
    }

    return 0;
}

错误示例及调试方法

下面是一个错误的示例代码,其中尝试在空的vector中访问元素,这将导致运行时错误。

错误示例代码

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec;

    std::cout << "Element at index 0: " << vec[0] << std::endl;  // 尝试访问空vector中的元素

    return 0;
}

调试方法

  1. 检查容器状态:在访问元素之前,检查容器是否已经初始化且非空。
  2. 使用迭代器:使用迭代器访问元素可以避免索引越界的问题。
  3. 使用条件判断:在访问元素之前,使用条件判断确保元素存在。

调试后的代码

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec;

    if (!vec.empty()) {
        std::cout << "Element at index 0: " << vec[0] << std::endl;
    } else {
        std::cout << "Vector is empty, no element to access." << std::endl;
    }

    return 0;
}

通过上述调试方法,可以避免在空容器中访问元素导致的错误。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消