Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >学好这13种数据结构,应对各种编程语言(C++版)

学好这13种数据结构,应对各种编程语言(C++版)

作者头像
五分钟学算法
发布于 2019-07-14 06:08:01
发布于 2019-07-14 06:08:01
1.5K00
代码可运行
举报
文章被收录于专栏:五分钟学算法五分钟学算法
运行总次数:0
代码可运行

学了这么长时间数据结构和算法,有必要来个总结了,顺便回顾一下我们这段时间的学习成果。以 C++ 语言本身提供的数据结构为例。如果能掌握这 13 种数据结构,相信在学习其它语言的时候就不费劲了。

数组 Array

数组在初始化的时候就需要知道其大小,后续是不可以改变其大小的,可以通过下标来获取某个 index 中存放的元素。在 C++ 中通过源码可以知道,它其实是在 C 数组的基础上封装的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <array>void testArray() {    // 创建一个数组    std::array<int, 5> a = {2, 4, 6, 8, 10};    // 对数组进行遍历    for (const auto i : a) {        std::cout << i << std::endl;    }    for(int i = 0; i < a.size(); i++) {        std::cout << a[i] << std::endl;    }    // 取第一个值,通过 [index] 获取    std::cout << "a[0] = " << a[0] << std::endl;    // 修改数组中第一个值    a[0] = 5;    /**     at 会检查 index 是否越界,越界将 crash,而 a[index] 不会;     libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: array::at     */    a.at(0);    // 数组是否为空    a.empty();    // 求数组的长度    std::cout << "a.size()=" << a.size() << std::endl;    // 获取第4个值    int value = std::get<4>(a);    std::cout << "a(4) = " << value << std::endl;    // 创建一个空数组,数组中的值为0或者是与类型相等的其它值    std::array<int, 5> a2;    std::cout << "end a2" << a2[0] << std::endl;    // 比较两个数组中的元素是否都相等    if (a == a2) {}}

可变数组,向量vector

在C++中使用 Vector 存当可变数组,它的容量可以动态改变,初始化的时候不需要确定数组的大小。使用的方法和数组基本一致。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <vector>// 向量void testVector() {    /**     vector<T> 它与Array不同,它的大小是可变的     */    std::vector<std::string> v;    // 增加容器的容量,至少容纳 20 个元素    v.reserve(20);    // 初始化一个向量    std::vector<int> v2 = {2, 4, 5, 7};    // 以数组初始化一个vector    std::array<std :: string, 5> words {"one", "two","three", "four", "five"};    std::vector<std::string> words_copy {std::begin(words) , std::end(words)};    // 通过 v[index] 获取或者修改元素    std::cout << "v[0] = " << v2[1] << std::endl;    // 获取第一个元素    std::cout << "v.front() = " << v2.front() << std::endl;    // 在末尾插入值为 9    v2.push_back(9);    // 在末尾插入值为 2    v2.emplace_back(2);    // 删除第一个元素,传入的值是一个迭代器    v2.erase(v2.begin());    // 长度    v2.size();    // 删除所有元素    v2.clear();    // 删除末尾元素    v2.pop_back();    // 在末尾插入元素    v2.insert(v2.end(), 3);}

双向链表 list

双向链表具有指向前一个节点和后一个节点的指针。C++ 中本身提供了双向链表的实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <list>void testList() {    list<string> words {"hello", "list"};    // 头部插入元素    words.push_front("push_fron");    words.emplace_front("emplace_front");    // 尾部插入    words.push_back("push_back");    words.emplace_back("emplace_back");    // 指定位置插入    words.insert(words.begin()++, "insert");    // 删除元素    words.remove("push_fron");    // 通过迭代器来访问链表中的元素    list<string>::iterator beg_iter = words.begin();    list<string>::iterator end_iter = words.end();    cout << "beg_iter:" << *beg_iter << endl;    cout << "end_iter:"  << *end_iter << endl;        for (auto a : words) {        cout << a << endl;    }}

单链表 forward_list

单链表只有指向下一个节点的指针,前面关于单链表我们做了好多算法题。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <forward_list>void testForwardList() {    forward_list<string> flist {"name", "lefe", "hello"};    // 计算它的大小    auto count = distance(begin(flist), end(flist));    cout << "size:" << count << endl;    // 头部插入    flist.push_front("before3");    // 在头部插入    flist.insert_after(flist.begin(), "before2");    // 在头结点前面插入    flist.insert_after(flist.before_begin(), "before1");    // 遍历单链表    for (auto word : flist) {        cout << word << endl;    }}

队列 queue

队列是一种先进先出的数据结构,C++底层使用「双端队列」实现。关于队列的更多内容,可以看这篇内容 图解设计一个循环队列。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <queue>void testQueue() {    queue<int> s;    // 入队    s.push(1);    // 出队    s.pop();    // 队首    s.front();    // 队尾    s.back();    // 队大小    s.size();}

双端队列deque

双端队列可以对队头和队尾元素进行操作。在做算法的时候我们设计过一个双端队列 图解设计一个双端队列

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void testDeque() {   // 初始化一个空双端队列    deque<int> my_deque;    // 初始化一个含有两个元素双端队列    deque<string> name_queue {"lefe", "wsy"};    cout << "[0] = " <<  name_queue[0] << endl;    // 获取队头元素    cout << "front = " <<  name_queue.front() << endl;    // 获取队尾元素    cout << "back = " <<  name_queue.back() << endl;    // 从尾部入队    name_queue.push_back("bx");    name_queue.pop_front();}

优先队列 priority_queue

优先队列和普通队列一样只能在队尾插入元素,队头删除元素,但是它有一个特点,队头永远是优先级最大的元素,出队顺序与入队顺序无关。C++ 中的底层使用「堆」实现的,这样时间复杂度可以控制在 O(logn)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void testPriorityQueue() {    // 创建优先队列    priority_queue<int> q;    // 向队列中添加元素    q.push(4);    q.push(1);    for(int i = 0 ; i < q.size() ; i++) {        cout << q.top() << endl;        // 删除第一个元素        q.pop();    }    // 队列是否为空    q.empty();}

堆heap

堆是一颗完全二叉树,某个节点的值总是不大于父节点的值(大根堆),可以使用数组来表示一个堆,C++ 默认提供的是大根堆。在堆排序中我们有详细介绍了堆。图解排序 6/10 - 堆排序(题目写出了)。在这篇文章中,我们实现了一个堆 动手写个“堆”

C++ 中的堆是通过算法实现的,需要导入 #include <algorithm>

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <algorithm>void testHeap() {    vector<int> numbers {6, 20, 7, 3, 5};    /**提供判断方法*/    // make_heap(numbers.begin(), numbers.end(), [](int a,int b){return a < b;});    // 创建堆后,numbers 中元素的值为: 20,6,7,3,5,大根堆    make_heap(numbers.begin(), numbers.end(), [](int a,int b){return a < b;});    // 向堆中添加元素    numbers.push_back(40);    // 重组堆:40,6,20,3,5,7 大根堆,调用 push_heap 先确保先前的 vertor 是个堆    push_heap(numbers.begin(), numbers.end());    // 移除堆顶元素,需要把 numbers 中的尾部元素移除,不会自动移除    pop_heap(numbers.begin(), numbers.end());    numbers.pop_back();}

栈 stack

栈是一种先进后出的数据结构,C++ 底层使用双端队列实现。在以前最小栈算法中我们详细介绍了这种数据结构。图解最小栈(LeetCode155. Min Stack)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stack>void testStack() {    stack<int> s;    s.push(1);    s.pop();    cout << "top=" << s.top() << endl;    s.size();}

映射 map、unordered_map

map 是一种保存 key 和 vaule 的数据结构,key 是唯一的。C++ 中提供了有序的 map 和无序的 map 「unordered_map」。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <unordered_map>#include <map>void testMap() {    // 初始化    map<string, string> m;    pair<map<string, string>::iterator, bool> ret_iter =     m.insert(pair<string, string>("name", "lefe"));    if (ret_iter.second == false) {        cout << "name have existed" << endl;    }    // 初始化    map<int, string> m2 = {        {2014, "iOS"},        {2015, "Android"},    };    // 单值插入    m["name"] = "wsy";    // 多值插入    m.insert({{"age", "20"}, {"from", "nmg"}});    cout << "size = " << m.size() << endl;    // 使用迭代器删除    m.erase(m.begin());    // 查找    map<string, string>::iterator find_iter = m.find("from");    if (find_iter != m.end()) {        cout << "find" << endl;    }    // 遍历, key 是有序的    for (pair<string, string> v : m) {        cout << v.first << " = " << v.second << endl;    }    // 删除全部元素    m.clear();}

pair

pair中保存了两个值,这两个值的类型可以是任意类型,也可以不同。通过 first 和 second 来获取对应的值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void testPair() {    pair<string, string> p = {"name", "lefex"};    // 通过first 和 second 来获取第一个和第二个值    cout << p.first;    cout << p.second;}

元组 tuple

它是 pair 的扩充版,可以存储多个不同类型的元素。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void testTuple() {    pair<string, string> p = {"name", "lefe"};    // 创建一个 tuple,类型为 <strinng, int, double, pair>    auto my_tuple = make_tuple("name", 20, 10.3, p);    // 获取第一个元素    cout << "0 = " << get<0>(my_tuple) << endl;    // 获取第二个元素    cout << "1 = " << get<1>(my_tuple) << endl;}

集合 set

集合中不能存储相同的元素,它底层基于平衡二叉树实现,在前面的文章中我们通过二分搜索树实现了 set。使用 BST 实现 Set。在 C++ 中 set 是有序的,同时也提供了无序的 set 「UnorderSet」。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <set>#include <unordered_set>void testSet() {    set<int> s {7, 3, 4};    s.insert(5);    // 3,4,5,7    for (auto v : s) {        cout << v << endl;    }        unordered_set<int> us {7, 3, 4};    us.insert(5);    // 7,3,4,5    for (auto v : us) {        cout << v << endl;    }}

总结

我们介绍了 C++ 语言本身提供的数据结构,有线性结构和非线性结构。这些数据结构在其它语言中几乎也会提供,而且底层实现基本一致,所有只有掌握了这些数据结构原理,在学习一门其它语言变的非常轻松,调用 API 时更爽。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 五分钟学算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【C++修行之道】STL(初识pair、vector)
在C++中,pair是一个模板类,用于一对值的组合。它位于<utility>头文件中。pair类的定义如下:
走在努力路上的自己
2024/01/26
8640
【C++修行之道】STL(初识pair、vector)
C++13-STL模板
在线练习: http://noi.openjudge.cn/ https://www.luogu.com.cn/
用户2225445
2023/10/16
3220
C++13-STL模板
10min快速回顾C++语法(八)STL专题
⭐写在前面的话:本系列文章旨在短时间内回顾C/C++语法中的重点与易错点,巩固算法竞赛与写题过程中常用的语法知识,精准地解决学过但有遗忘的情况,为算法刷题打下坚实的基础。
timerring
2022/09/26
3100
c++ list, vector, map, set 区别与用法比较
List封装了链表,Vector封装了数组, list和vector得最主要的区别在于vector使用连续内存存储的,他支持[]运算符,而list是以链表形式实现的,不支持[]。 Vector对于随机访问的速度很快,但是对于插入尤其是在头部插入元素速度很慢,在尾部插入速度很快。List对于随机访问速度慢得多,因为可能要遍历整个链表才能做到,但是对于插入就快的多了,不需要拷贝和移动数据,只需要改变指针的指向就可以了。另外对于新添加的元素,Vector有一套算法,而List可以任意加入。 Map,Set属于标准
hbbliyong
2018/03/06
10.2K0
c++ list, vector, map, set 区别与用法比较
学了C++不会STL,简直少了左膀右臂
容器(Container): 是一种数据结构,如list,vector,和deques ,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器; 迭代器(Iterator): 提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器也可以是那些定了operator*()以及其他类似于指针的操作符地方法的类对象; 算法(Algorithm): 是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用; 仿函数(Functor) 适配器(Adaptor) 分配器(allocator) 仿函数、适配器、与分配器用的比较少,甚至没用过!在这里不做说明,有兴趣可以自己学习一下,那个东西C++软件工程可能用的比较多。
风骨散人Chiam
2020/10/28
8580
【C++】详解 stack && queue && priority_queue && deque
​ 通过观察文档我们不难发现,接口相较于之前的 string、vector 和 list 少了很多。它甚至连拷贝构造和析构都没有自己实现,然而这些都得益于容器适配器的使用。
利刃大大
2025/02/12
830
【C++】详解 stack && queue && priority_queue && deque
C++从 STL 中的队列开始说起
队列遵循先进先出的存储原则,类似于一根水管,水从一端进入,再从另一端出去。进入的一端称为队尾,出去的一端称为队头。
一枚大果壳
2022/12/20
9410
C++从 STL 中的队列开始说起
一万五千字C++STL【容器】详解 (全网最详细)
一般大多数的题目都可以使用vector容器,除非有特定需求使用其他容器更加合理方便;
C语言与CPP编程
2023/09/06
3.1K0
一万五千字C++STL【容器】详解 (全网最详细)
STL标准库容器
STL对定义的通用容器分三类:顺序性容器、关联式容器和容器适配器。 顺序性容器:vector、deque、list 关联性容器:set、multiset、map、multimap 容器适配器:stack、queue
废江_小江
2022/09/05
2860
STL标准库容器
【精选】算法设计与分析(第一章概述知识点)
命运之光
2024/03/20
1970
【精选】算法设计与分析(第一章概述知识点)
【C++】基础:STL标准库常用模块使用
C++标准模板库(Standard Template Library,STL)是C++中的一个重要组成部分,提供了丰富的容器、算法和函数模板,可以帮助开发人员快速实现通用的数据结构和算法。STL的设计目标是提供高效、可靠、易于使用的工具,以提高开发效率和代码可维护性。
DevFrank
2024/07/24
1980
C++ STL (标准模板库) 详细内容讲解
顺序容器有以下三种:可变长动态数组 vector、双端队列 deque、双向链表 list。
杨鹏伟
2020/09/11
2.1K0
3.1 C++ STL 双向队列容器
双向队列容器(Deque)是C++ STL中的一种数据结构,是一种双端队列,允许在容器的两端进行快速插入和删除操作,可以看作是一种动态数组的扩展,支持随机访问,同时提供了高效的在队列头尾插入和删除元素的操作。
王瑞MVP
2023/08/16
4440
❤ 挑战C站最强C++ STL标准库总结(内含大量示例)
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家,(ノ´▽`)ノ♪-》点击这里->一个宝藏级人工智能教程网站。
全栈程序员站长
2022/09/09
1.4K0
❤ 挑战C站最强C++ STL标准库总结(内含大量示例)
STL 常用操作
a.push_back(x)把元素x插入到vector a的尾部。 a.pop_back()删除vector a的最后一个元素。
浪漫主义狗
2022/11/02
7970
C++ STL 标准模板库(容器总结)算法
C++ 标准模板库STL,是一个使用模板技术实现的通用程序库,该库由容器container,算法algorithm,迭代器iterator,容器和算法之间通过迭代器进行无缝连接,其中所包含的数据结构都是目前最优解,该库既能保证软件代码的高可复用性,又能保证代码具有相当高的执行效率,STL库是ANSI/ISO的C++标准的具体实现,任何标准库的实现都是以源码形式释出的.
王瑞MVP
2022/12/28
2.4K0
C++STL入门汇总(OJ必备)
做了没多少OJ题目,就发现了自己在STL使用的不足,明明可以更简单的完成一些工作,却总是因为不懂STL完全自己设计,导致对于一些简单问题仍然花费很多时间。因此,学习STL迫在眉睫!!!
种花家的奋斗兔
2020/11/13
9920
C++的输入输出特点、运算符重载及标准模板库STL
程序的输入都建有一个缓冲区,即输入缓冲区。一次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。正因为cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入。 注意:cin>>和cin.get()都残留数据不会出错,但是cin.getline会报错,下面的示例中都有体现。
Here_SDUT
2022/06/29
8420
C++的输入输出特点、运算符重载及标准模板库STL
【C++】C++提高编程部分-泛型编程-STL
函数模板作用: 建立一个通用的函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表。
半生瓜的blog
2023/05/12
2.7K0
【C++】C++提高编程部分-泛型编程-STL
C++和Java中STL库入门[通俗易懂]
STL简称标准模版库,被容纳在C++标准程序库,包含了许多基本数据结构和基本算法,使程序员写起来得心应手。
全栈程序员站长
2022/09/27
1.4K0
相关推荐
【C++修行之道】STL(初识pair、vector)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验