个人技术分享

以下是一些常用的STL容器:

  • vector:动态数组,提供快速的随机访问。
  • list:双向链表,支持快速插入和删除操作。
  • set:有序集合,存储唯一的元素。
  • map:有序映射,存储键值对。
  • stack:堆栈,先进后出(LIFO)的数据结构。
  • queue:队列,先进先出(FIFO)的数据结构。

算法

STL提供了丰富的算法库,包括排序、搜索、复制、替换、合并等各种常用算法。这些算法可以用于不同类型的容器,使得对数据进行各种操作变得简单高效。

以下是一些常用的STL算法:

  • sort:对容器进行排序。
  • find:在容器中查找指定元素。
  • copy:将容器中的元素复制到另一个容器。
  • replace:替换容器中的元素。
  • merge:合并两个有序容器。
  • reverse:反转容器中的元素顺序

vector(动态数组)

vector 是一个动态数组,提供了连续的内存空间用于存储元素。它是最常用的容器之一,支持快速随机访问和动态调整大小。

头文件

#include <vector>

创建容器对象

std::vector<T> vec;  // 创建一个空的 vector,元素类型为 T
std::vector<T> vec(n);  // 创建包含 n 个默认初始化的元素的 vector
std::vector<T> vec(n, value);  // 创建包含 n 个初始化为 value 的元素的 vector

vector<vector<Point2f> > points; //定义一个二维数组
将v[begin(),end())区间中的元素拷贝给自身:
	vector<int>v2(v1.begin(), v1.end());

常用成员函数

size():返回 vector 中的元素数量。
empty():检查 vector 是否为空。
push_back(value):在 vector 的末尾添加一个元素。
pop_back():删除 vector 的最后一个元素。
front():访问 vector 的第一个元素。
back():访问 vector 的最后一个元素。
clear():清空 vector 中的所有元素。
insert(position, value):在指定位置插入一个元素。
erase(position):删除指定位置的元素。
erase(begin, end):删除指定范围内的元素。

在c++11里,为for循环,添加一个container,它就会自动迭代:实现了对于vector型变量vec的内容打印,变量 i 遍历vector中的每一个元素,直到vector的结束

vector<int> vec;		//定义一个vector型变量vec的内容打印
vec.push_back(10);		//  向容器vec中添加10个元素
vec.push_back(20);		//再向容器vec中添加20个元素

for(int i:vec)
	cout << i << endl;

list(双向链表)

list 是一个双向链表,它支持高效的插入和删除操作,但不支持随机访问。它可以在任意位置进行元素的插入和删除,适用于需要频繁插入和删除操作的场景。

头文件

#include <list>

创建容器对象

std::list<T> lst;  // 创建一个空的 list,元素类型为 T
std::list<T> lst(n);  // 创建包含 n 个默认初始化的元素的 list
std::list<T> lst(n, value);  // 创建包含 n 个初始化为 value 的元素的 list

常用成员函数

size():返回 list 中的元素数量。
empty():检查 list 是否为空。
push_back(value):在 list 的末尾添加一个元素。
push_front(value):在 list 的开头添加一个元素。
pop_back():删除 list 的最后一个元素。
pop_front():删除 list 的第一个元素。
front():访问 list 的第一个元素。
back():访问 list 的最后一个元素。
clear():清空 list 中的所有元素。
insert(position, value):在指定位置插入一个元素。
erase(position):删除指定位置的元素。
erase(begin, end):删除指定范围内的元素。

#include <iostream>
#include <list>

int main() {
    std::list<int> lst;  // 创建一个空的 list

    lst.push_back(1);  // 在末尾添加元素
    lst.push_back(2);
    lst.push_front(0);  // 在开头添加元素

    std::cout << "List size: " << lst.size() << std::endl;  // 输出元素数量
    std::cout << "List elements: ";
    for (int num : lst) {
        std::cout << num << " ";  // 遍历并输出元素
    }
    std::cout << std::endl;

    lst.pop_back();  // 删除最后一个元素

    std::cout << "List size after pop_back(): " << lst.size() << std::endl;
    std::cout << "New list elements: ";
    for (int num : lst) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

map(关联容器)

map 是一个关联容器,它提供了一对一的键值对存储和访问功能。它基于红黑树

实现,具有自动排序的特性,键值对按键进行排序,并且可以快速地进行插入、删除和查找操作。

插入元素的键不允许重复,比较函数只对元素的键值进行

头文件

#include <map>

创建容器对象

std::map<Key, T> mp;  // 创建一个空的 map,键类型为 Key,值类型为 T
std::map<Key, T> mp(other);  // 创建另一个 map 的副本

常用成员函数

size():返回 map 中的键值对数量。
empty():检查 map 是否为空。
insert({key, value}):插入一个键值对到 map 中。
erase(key):删除指定键的键值对。
clear():清空 map 中的所有键值对。
find(key):查找指定键对应的迭代器。返回的是迭代器
begin():返回指向第一个键值对的迭代器。
end():返回指向最后一个键值对之后的迭代器。

coust(key):返回是否有键为key的元素,若有则返回1,若没有则返回0

pair是map内部的存储结构,pair就是“一对”,第一个元素和第二个元素组成的一对,其中第一个元素叫做first,第二个元素叫second。

pair类似于结构体,里面的元素是first和second

一个map变量中的值以pair的形式存在,可以有多个pair,每个pair中存储两个值

#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> mp;  // 创建一个空的 map

    mp.insert({"Alice", 25});  // 插入键值对
    mp.insert({"Bob", 30});
    mp["Charlie"] = 35;  // 也可以使用索引操作符插入键值对

    std::cout << "Map size: " << mp.size() << std::endl;  // 输出键值对数量
    std::cout << "Map elements:" << std::endl;
    for (const auto& pair : mp) {
        std::cout << pair.first << ": " << pair.second << std::endl;  // 遍历并输出键值对
     
    }

    mp.erase("Bob");  // 删除指定键的键值对

    std::cout << "Map size after erase(): " << mp.size() << std::endl;
    std::cout << "New map elements:" << std::endl;
    for (const auto& pair : mp) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

注意:map会自动对键进行排序,从小到大排序

set(关联容器)

set 是一个关联容器,它存储唯一的元素,且自动按照键进行排序。set 的底层实现基于红黑树,具有快速的插入、删除和查找操作。

因此set可以进行去重和排序操作

头文件

#include <set>

创建容器对象

std::set<T> st;  // 创建一个空的 set,元素类型为 T
std::set<T> st(other);  // 创建另一个 set 的副本
将v[begin(),end())区间中的元素拷贝给自身:
	set<int>v2(v1.begin(), v1.end());

常用成员函数

size():返回 set 中的元素数量。
empty():检查 set 是否为空。当set为空时,返回真
insert(value):向 set 中插入一个元素。
erase(value):删除 set 中指定的元素。
clear():清空 set 中的所有元素。
find()函数返回一个迭代器,指向范围内搜索元素的第一次出现。如果没有找到目标元素,则返回该容器的end()
begin():返回指向第一个元素的迭代器。
end():返回指向最后一个元素之后的迭代器。

cout(x): 统计set中,x的数量,因此要么返回1,要么返回0 

#include <iostream>
#include <set>

int main() {
    std::set<int> st;  // 创建一个空的 set

    st.insert(10);  // 插入元素
    st.insert(20);
    st.insert(30);

    std::cout << "Set size: " << st.size() << std::endl;  // 输出元素数量
    std::cout << "Set elements: ";
    for (int num : st) {
        std::cout << num << " ";  // 遍历并输出元素
    }
    std::cout << std::endl;

    st.erase(20);  // 删除指定元素

    std::cout << "Set size after erase(): " << st.size() << std::endl;
    std::cout << "New set elements: ";
    for (int num : st) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

unordered_set

底层是hash

引入头文件:

#include <unordered_set>

unordered_set 容器,可直译为“无序 set 容器”。即 unordered_set 容器和 set 容器很像,唯一的区别就在于 set 容器会自行对存储的数据进行排序,而 unordered_set 容器不会。

unordered_set的几个特性:

创建容器对象

unordered_set<int> set1;

常用成员函数

size()函数,返回元素的数量

empty()函数——判断是否为空,若容器为空,则返回 true;否则 false

find()函数——查找,查找2,找到返回迭代器,失败返回end()

count(x)函数——出现次数,返回x出现的次数,0或1

insert()函数——插入元素

//插入元素,返回pair<unordered_set<int>::iterator, bool>
set1.insert(3);
//使用initializer_list插入元素
set1.insert({1,2,3});
//指定插入位置,如果位置正确会减少插入时间,返回指向插入元素的迭代器
set1.insert(set1.end(), 4);
//使用范围迭代器插入
set1.insert(set2.begin(), set2.end());

关于insert函数的返回值:
insert()只传入单个参数(待插入元素)

auto pr = words.insert("ninety"); 

emplace()函数——插入元素(转移构造)

//使用转移构造函数添加新元素3,比insert效率高
set1.emplace(3);

erase(x)函数——删除元素x

stack(适配器容器)

stack 是一个适配器容器,它提供了栈(先进后出)的行为。stack 内部使用其他容器作为其底层实现,默认情况下使用 deque 作为底层容器。

头文件

#include <stack>

创建容器对象

std::stack<T> stk;  // 创建一个空的 stack,元素类型为 T

常用成员函数

  • size():返回 stack 中的元素数量。
  • empty():检查 stack 是否为空。
  • push(value):将元素压入 stack。
  • pop():弹出 stack 的顶部元素。
  • pop()是stack类的一个成员函数,用于移除stack顶部(即最后压入的)的元素,但并不返回该元素的值。
  • top():返回 stack 的顶部元素的引用。
#include <iostream>
#include <stack>

int main() {
    std::stack<int> stk;  // 创建一个空的 stack

    stk.push(10);  // 将元素压入 stack
    stk.push(20);
    stk.push(30);

    std::cout << "Stack size: " << stk.size() << std::endl;  // 输出元素数量
    std::cout << "Stack top: " << stk.top() << std::endl;  // 输出栈顶元素

    stk.pop();  // 弹出栈顶元素

    std::cout << "Stack size after pop(): " << stk.size() << std::endl;
    std::cout << "New stack top: " << stk.top() << std::endl;

    return 0;
}

queue(适配器容器)

queue 是一个适配器容器,它提供了队列(先进先出)的行为。queue 内部使用其他容器作为其底层实现,默认情况下使用 deque 作为底层容器。

头文件

#include <queue>

创建容器对象

std::queue<T> que;  // 创建一个空的 queue,元素类型为 T

常用成员函数

size():返回 queue 中的元素数量。
empty():检查 queue 是否为空。

分别输出1和0
最开始队列为空,返回值为1(ture);
插入两个元素后,队列不为空,返回值为0(false);


push(value):将元素加入到 queue 的末尾。
pop():移除 queue 的首个元素。
front():返回 queue 的首个元素的引用。
back():返回 queue 的末尾元素的引用。

#include <iostream>
#include <queue>

int main() {
    std::queue<int> que;  // 创建一个空的 queue

    que.push(10);  // 将元素加入到 queue 的末尾
    que.push(20);
    que.push(30);

    std::cout << "Queue size: " << que.size() << std::endl;  // 输出元素数量
    std::cout << "Queue front: " << que.front() << std::endl;  // 输出队首元素
    std::cout << "Queue back: " << que.back() << std::endl;  // 输出队尾元素

    que.pop();  // 移除队首元素

    std::cout << "Queue size after pop(): " << que.size() << std::endl;
    std::cout << "New queue front: " << que.front() << std::endl;

    return 0;
}

deque(双端队列)

头文件

deque是C++ 标准模板库的一部分,因此,想要使用deque,需要在程序中包含头文件deque

# include <deque>

创建容器对象

定义deque的常用方式如下所示:

deque<Type> v1; 				//v1是一个空deque,可存储元素类型为T,执行默认初始化
deque<Type> v2(v1);			//v2中包含v1中的所有元素
deque<Type> v2 = v1;			//等价于v2(v1)
deque<Type> v3(n,value);		//v3中有n个元素,并且值都为value
deque<Type> v4(n);				//v4包含了n个重复执行了值初始化的对象
deque<Type> v5{a,b,c.....};	//v5包含大括号中的所有元素
deque<Type> v6 = {a,b,c...};	//等价于v5{a,b,c....}

deque的迭代器

常用成员函数

size() 元素个数

 max_size()——最多能容纳元素个数:

empty()——判断deque是否为空

如果有元素,返回false;如果没有元素,返回true

at()——访问deque元素

使用元素的索引来访问deque,其中at(index)中index为索引,必须是合法的。

 front()和back()——访问deque头尾元素

 assign()——指定deque元素

用法一:deque.assign(num,value)

用法二:deque.assign(iterator1,iterator2)

这种用法会用两个迭代器iterator1和iterator2之间的元素覆盖deque的元素,迭代器可以是原来deque的迭代器,也可以是其他deque的迭代器,注意区间是左闭右开[iterator1,iterator2),即iterator1指向的元素在区间内,iterator2指向的元素不在区间

push_back()——添加元素(deque尾部)

 push_front()——添加元素(deque头部)

pop_back()——移除deque元素(尾部)

 pop_front()——删除deque元素(头部)

insert()——添加元素(任意位置)

​​​​​​​
 

STL 算法

STL(标准模板库)提供了丰富的算法,用于在容器上执行各种操作。这些算法大大简化了对数据集合的处理,包括搜索、排序、转换等操作。

以下是一些常用的 STL 算法:

std::find():在容器中查找指定的元素。
std::sort():对容器中的元素进行排序。
std::reverse():反转容器中的元素顺序。
std::count():统计容器中某个值的出现次数。
std::accumulate():计算容器中元素的累加和。
std::transform():对容器中的元素应用一个操作,并将结果存储在另一个容器中。
std::copy():将一个容器中的元素复制到另一个容器中。
std::remove():从容器中删除指定的值。
std::unique():删除容器中的重复元素。
std::min_element():查找容器中的最小元素。
std::max_element():查找容器中的最大元素。

这些算法都是通过包含 <algorithm> 头文件来使用的。它们适用于不同类型的容器,包括数组、向量、列表、集合等。

下面是一个示例代码,演示了如何使用 STL 算法:

std::reverse()

算法用于反转容器中的元素顺序。

void reverse( BidirIt first, BidirIt last );
  • first 和 last:定义了容器中要进行反转的元素的范围。这个范围是一个双向迭代器可以在正向和反向方向上进行遍历。

下面是一个示例代码:

#include <iostream>
#include <algorithm>
#include <vector>

int main() {
    std::vector<int> nums = {1, 2, 3, 4, 5};

    std::reverse(nums.begin(), nums.end());

    std::cout << "Reversed container: ";
    for (int num : nums) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}