2021-01-21

STL容器

一、顺序容器   顺序容器的元素排列次序与元素值无关

      vector/deque/list/forward_list/array/string

二、关联容器 顺序容器的元素排列次序与元素值有关

      有序容器:set/multiset/map/multimap -----红黑树

      无序容器:unordered set/unordered multiset/unordered map/unordered multimap ----- 哈希表

三、STL容器适配器 以既有的容器为底部结构,改变接口

     stack/queue/priority_queue

vector

可变大小数组;

支持快速随机访问;

在尾部之外的位置插入和删除元素可能很慢;

两个重要方法:

erase:返回迭代器指向被删除元素的下一个元素

iter = v.erase(iter);

    // vector删除
    vector<int> v1 = {2, 5, 3, 4, 5, 5, 2, 2, 0, 4};
    // 删除所有的5
    for (auto iter = v1.begin(); iter != v1.end();) {
        if (*iter == 5) {
            v1.erase(iter); // 或者 iter = v1.erase(iter);
        } else {
            ++iter;
        }
    }
    for_each(v1.begin(), v1.end(), [](int i){ cout << i << ","; });

insert:返回迭代器指向插入的元素

    // vector插入
    vector<int> v2 = {2, 5, 3, 4, 5, 5, 2, 2, 0, 4};
    // insert 6 before every 5
    for (auto iter = v2.begin(); iter != v2.end(); iter++) {
        if (*iter == 5) {
            iter = v2.insert(iter, 6);
            ++iter; // 此时iter指向6, ++后指向5, 在for中++后指向5的下一个元素
        }
    }
    for_each(v2.begin(), v2.end(), [](int i){ cout << i << ","; });

deque

双向开口,双向进出;

动态分段连续空间组合而成,不存在vector那样因空间不足重新配置,导致元素大量赋值的问题

支持随机访问,访问效率远大于vector

首尾删,指针都不会失效;

首尾增,可能导致管控中心map重新配置,指针不会失效,但是迭代器失效

中间删,需要保证连续性,会造成前面或者后面所有指针失效;

中间增,若导致map重新配置,会造成指针有效但是迭代器失效

string

定义如下:

/// A string of @c char
typedef basic_string<char>  string;

array

固定大小的数组,比原生数组的功能多

array<int, 5> arr1 = {1, 2, 3, 4, 5};
auto arr2 = arr1;   // array支持复制

try {
    cout << arr1.at(5) << endl;    // at函数支持越界检查
} catch(exception &e) {
    cout << e.what() << endl;
} 

std::sort()

只有随机访问迭代器才可以使用sort()/stable_sort()

前向迭代器++ forward_list   快速排序  归并排序

后向迭代器-                          堆排序     插入排序

双向迭代器 ++ --  list map set  插入排序

随机迭代器++ -- +n -n    vector deque string array 原生数组

#include <iostream>
#include <list>
#include <algorithm>
int main()
{
    list<int> l = {5, 4, 3, 2, 1};
    l.sort();       // list排序只能使用sort(),不能使用stable_sort()
    for_each(l.begin(), l.end(), [](int i){ cout << i << ",";});
    return 0;
}
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
    int arr[] = {5, 4, 3, 2, 1};
    string str("Hello World");
    sort(arr, arr + 5);
    stable_sort(str.begin(), str.end());
    int len = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < len; i++) {
        cout << arr[i] << ", ";
    }
    cout << endl;
    for_each(str.begin(), str.end(), [](char i){ cout << i << ",";});
    return 0;
}

list

双向循环链表,不支持随机访问,插入删除效率高

增删节点后,只需要修改指针,所有元素的位置都不变,所以迭代器都没失效

但是遍历删除的时候,需要小心

前置的++返回引用;后置++返回临时变量

#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
int main()
{
    list<int> l1 = {2, 5, 3, 4, 5, 5, 2, 2, 0, 4};
    // delete all 5
    for (auto iter = l1.begin(); iter != l1.end();) {
        if (*iter == 5) {
            // list删除时需要iter++,否则执行错误
            l1.erase(iter++);    // 或者iter = l1.erase(iter);
        } else {
            ++iter;
        }
    }
    for_each(l1.begin(), l1.end(), [](int i){ cout << i << ", ";});
    
    cout << endl;
    
    vector<int> v1 = {2, 5, 3, 4, 5, 5, 2, 2, 0, 4};
    // 删除所有的5
    for (auto iter = v1.begin(); iter != v1.end();) {
        if (*iter == 5) {
            v1.erase(iter); // 或者iter = v1.erase(iter);
        } else {
            ++iter;
        }
    }
    for_each(v1.begin(), v1.end(), [](int i){ cout << i << ", "; });
    return 0;
}

set/map

元素并非连续存放,插入删除时原有的迭代器都不会失效,操作方式同list;

元素位置和key值强相关,key值不可修改;

自定义类型作为key时,需要重载operator <;

a < b 和b <a 都是false的时候需要重构operator==;

#include <iostream>
#include <set>
#include <algorithm>
struct C1 {
    int data;
    // 运算符重载
    bool operator< (const C1 &c1) const
    {
        return data < c1.data;
    }
};
int main(int argc, const char *argv[])
{
    using namespace std;
    C1 c1[5] = {5, 4, 3, 2, 1};
    set<C1> s;
    for (auto e : c1) {
        s.insert(e);
    }
    cout << "iter->data: ";
    for (auto iter = s.begin(); iter != s.end(); iter++) {
        cout << iter->data << ",";
    }
    return 0;
}

unordered_set/unordered_map

无序容器,底层结构 ---- 哈希表

无排序功能,插入和查找效率高于set/map

对于自定义类型,需要重载operator==,并提供哈希函数(基本类型以及string,系统都已经内置)

stack,queue

不是真实的容器,是对某种底层容器封装的适配器,默认底层容器是deque,也可以是vector,list或者其他符合要求的容器

stack和queue都不支持遍历操作,也没有相应的迭代器

priority_queue 优先队列/堆

priority也是适配器,默认底层容器是vector,支持的函数和queue一样,只是出队规则不同

内部元素并非按照入队先后排列,而是按照一定的权值排列,priority本质上是堆

因为堆调整需要随机访问能力,所以底层容器必须有随机访问迭代器

找出数组中最大的元素 ----->找出数组中第k大的元素

优先队列求解复杂度:O(n.logk)

其他方法:

排序求解复杂度:O(n.longn)

用普通数组保存前k,复杂度:O(n.k)

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
// 输出第k大的数字
void topK(const vector<int> &v, int k)
{
    priority_queue<int, vector<int>, std::greater<int>> p;
    for (const auto e : v) {
        p.push(e);              // 从小到大入队
        if (p.size() > k) {     // 维持大小为k的优先队列,如果队列大于k,将最先入队的弹出
            p.pop();
        }
    }
    cout << p.top() << endl;    // 队头显示的就是第k大的
}
int main()
{
    vector<int> v2 = {2, 5, 3, 4, 5, 5, 2, 2, 0, 4};
    sort(v2.begin(), v2.end());
    for_each(v2.begin(), v2.end(), [](int i){ cout << i << ", "; });
    cout << endl;
    int k = 7;
    topK(v2, k);
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值