255 lines
6.9 KiB
C++
255 lines
6.9 KiB
C++
#include "STLUse.h"
|
|
#include <algorithm>
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <stack>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
|
|
void show_demo()
|
|
{
|
|
stack_demo();
|
|
adapter_demo();
|
|
search_demo();
|
|
}
|
|
|
|
// 概述
|
|
void summarize()
|
|
{
|
|
// 1.STL: 容器、算法、迭代器、仿函数、适配器、空间配置器。
|
|
|
|
// 2.容器
|
|
// (1)顺序容器: vector[动态数组]、deque[双向队列]、list[双向链表]
|
|
// (2)关联容器:set/multiset[集合]、map/multimap[字典]
|
|
// (3)容器适配器<从deque封装>:stack[栈]、queue[队列]、priority_queue[优先级队列]
|
|
|
|
// 3.各容器简介
|
|
// (1)vector: 内存连续。
|
|
// (2)deque: 内存连续,在两端增删具有较佳的性能。
|
|
// (3)list: 内存不连续,不随机存取。
|
|
// (4)集合带 multi 的,允许 key 重复。
|
|
|
|
// 4.map hashtable deque list实现原理
|
|
// (1)map: 内部是红黑树实现,可以自动排序,因此内部元素是有序的。
|
|
// (2)hashtable: 函数映射的思想记录存储位置和关键字。
|
|
// (3)deque: 内部实现是双向队列。
|
|
// (4)list: 内部实现是双向链表。
|
|
|
|
// 5.容器操作复杂度
|
|
// (1)vector,插入[O(N)]、查看[O(1)]、删除[O(N)]。
|
|
// (2)deque,插入[O(N)]、查看[O(1)]、删除[O(N)]。
|
|
// (3)list,插入[O(1)]、查看[O(N)]、删除[O(1)]。
|
|
// (4)map、set、multiset、multimap<红黑树,平衡二叉树>,插入[O(logN)]、查看[O(logN)]、删除[O(logN)]。
|
|
// (5)unordered_map、unordered_set、unordered_multimap、
|
|
// unordered_multiset:
|
|
// 插入:O(1),最坏O(N)
|
|
// 查看:O(1),最坏O(N)
|
|
// 删除:O(1),最坏O(N)
|
|
|
|
// x.空间适配器
|
|
}
|
|
|
|
void stack_demo()
|
|
{
|
|
std::stack<SimuData> stack{};
|
|
|
|
// 不提供遍历行为
|
|
SimuData da{};
|
|
da.data_ = 89;
|
|
da.value_ = 5.2;
|
|
|
|
stack.push(da);
|
|
|
|
while (!stack.empty()) {
|
|
std::cout << stack.top().data_ << std::endl;
|
|
stack.pop(); // 出栈
|
|
}
|
|
}
|
|
|
|
void queue_demo() // 队列
|
|
{
|
|
// 无迭代器
|
|
}
|
|
|
|
void list_demo()
|
|
{
|
|
// 双向循环链表
|
|
// 性质:插入删除操作不会造成原有的迭代器实现,vector 不行。
|
|
}
|
|
|
|
void set_demo()
|
|
{
|
|
// 特性:key 会被自动排序,不允许有重复的值。
|
|
// set 的 iterator 是一种 const_iterator,因为 set的元素值就是
|
|
// 键值,关系到 set 元素的排序规则。
|
|
}
|
|
|
|
void multi_set_demo()
|
|
{
|
|
// 与 set 特性用法一致。差别在于可以key重复。
|
|
// 与 set 一样底层实现使用的是红黑树。
|
|
}
|
|
|
|
// binary_function 指二元 (这个函数被标记了 弃用)
|
|
// class A : public std::binary_function<int, int, void>
|
|
// {
|
|
// public:
|
|
// void operator()(int val, int start) const
|
|
// {
|
|
// std::cout << "val:" << val << " start:" << start
|
|
// << " total:" << val + start << "\n";
|
|
// }
|
|
// };
|
|
|
|
// 取反适配器 (unary_function 这个函数被标记了 弃用)
|
|
// class MGreator : public std::unary_function<int, bool>
|
|
// {
|
|
// public:
|
|
// bool operator()(int val) const
|
|
// {
|
|
// // 大于 3
|
|
// return val > 3;
|
|
// }
|
|
// };
|
|
|
|
void my_print(int val) { std::cout << val << std::endl; }
|
|
void my_print2(int val, int start)
|
|
{
|
|
std::cout << val << " " << start << std::endl;
|
|
}
|
|
|
|
class Person
|
|
{
|
|
public:
|
|
Person(std::string name, int age)
|
|
{
|
|
name_ = name;
|
|
age_ = age;
|
|
}
|
|
void print()
|
|
{
|
|
std::cout << age_ << " ";
|
|
std::cout << name_ << "\n";
|
|
}
|
|
std::string name_{};
|
|
int age_{};
|
|
};
|
|
|
|
void my_print3(const Person& person)
|
|
{
|
|
std::cout << person.age_ << " ";
|
|
std::cout << person.name_ << "\n";
|
|
}
|
|
|
|
// 仿函数的目的:协助算法完成不同的策略。
|
|
void adapter_demo()
|
|
{
|
|
std::vector<int> vec{};
|
|
vec.push_back(1);
|
|
vec.push_back(2);
|
|
vec.push_back(3);
|
|
vec.push_back(4);
|
|
vec.push_back(5);
|
|
|
|
// bind2nd 将45绑定到第二个参数, bind1st 将45绑定到第一个参数
|
|
// 《函数对象适配器》 (bind2nd 这个函数被标记了 弃用)
|
|
// std::for_each(vec.begin(), vec.end(), std::bind2nd(A(), 45));
|
|
|
|
// std::vector<int>::iterator iter =
|
|
// std::find_if(vec.begin(), vec.end(), MGreator());
|
|
// if (iter != vec.end()) {
|
|
// // 找到 *iter
|
|
// std::cout << *iter << std::endl;
|
|
// }
|
|
// (not1 ==> 一元的取反)
|
|
// iter = std::find_if(vec.begin(), vec.end(), std::not1(MGreator()));
|
|
// if (iter != vec.end()) {
|
|
// // 找到 *iter
|
|
// std::cout << *iter << std::endl;
|
|
// }
|
|
|
|
// 这是另一个示例 deprecated-declarations (bind2nd 这个函数被标记了 弃用)
|
|
// iter = std::find_if(vec.begin(), vec.end(),
|
|
// std::not1(std::bind2nd(std::greater<int>(), 3)));
|
|
// if (iter != vec.end()) {
|
|
// // 找到 *iter
|
|
// std::cout << *iter << std::endl;
|
|
// }
|
|
|
|
// 《函数适配器》
|
|
std::for_each(vec.begin(), vec.end(), my_print);
|
|
// 将函数指针适配成函数的对象 ptr_fun (bind2nd ptr_fun 这个函数被标记了 弃用)
|
|
// std::for_each(vec.begin(), vec.end(),
|
|
// std::bind2nd(std::ptr_fun(my_print2), 1000));
|
|
|
|
// 《成员函数适配器》
|
|
std::vector<Person> pvec{};
|
|
pvec.emplace_back("A", 1);
|
|
pvec.emplace_back("B", 2);
|
|
pvec.emplace_back("C", 3);
|
|
pvec.emplace_back("D", 4);
|
|
pvec.emplace_back("E", 5);
|
|
std::for_each(pvec.begin(), pvec.end(), my_print3);
|
|
|
|
// 利用 mem_fun_ref 适配一下。 (mem_fun_ref 这个函数被标记了 弃用)
|
|
// std::for_each(pvec.begin(), pvec.end(), std::mem_fun_ref(&Person::print));
|
|
}
|
|
|
|
// 常用查找算法
|
|
void search_demo()
|
|
{
|
|
std::vector<int> demo{};
|
|
demo.push_back(23);
|
|
demo.push_back(21);
|
|
demo.push_back(87);
|
|
demo.push_back(11);
|
|
demo.push_back(11);
|
|
demo.push_back(6);
|
|
demo.push_back(90);
|
|
|
|
// find 直接按照值去查找
|
|
std::vector<int>::iterator iter = std::find(demo.begin(), demo.end(), 11);
|
|
if (iter != demo.end()) {
|
|
std::cout << *iter << std::endl;
|
|
}
|
|
// find_if 使用你提供的条件去查找
|
|
// 同理 count 和 count_if 也是如此。
|
|
|
|
// adjacent_find 查找相邻的重复元素
|
|
iter = std::adjacent_find(demo.begin(), demo.end());
|
|
if (iter != demo.end()) {
|
|
std::cout << "相邻的重复元素:" << *iter << std::endl;
|
|
}
|
|
|
|
// binary_search 二分查找法,需要有序。
|
|
}
|
|
|
|
void predicate_demo()
|
|
{
|
|
// 谓词是指普通函数或重载的operator(返回值是bool类型的函数对象(仿函数)
|
|
}
|
|
|
|
void traverse_demo()
|
|
{
|
|
// 遍历算法
|
|
// transform 用于搬运
|
|
}
|
|
|
|
// 排序
|
|
void sort_demo()
|
|
{
|
|
// merge 合并,两个容器需要有序
|
|
// sort 排序
|
|
// random_shuffle 随机调整次序
|
|
// reverse 翻转
|
|
}
|
|
|
|
// 集合算法
|
|
void set_algorithm_demo()
|
|
{
|
|
// set_intersection 求交集
|
|
// set_unin 求并集
|
|
// set_difference 差集
|
|
}
|