c++常用基础STL整理

map

  • 定义
map<char, int> mp
  • 用法:
    映射,mp[key]==value(key -> value)
    【key,value也可以是STL容器】
  • 特性
    map内部用红黑树实现(同set),map会以“key”从小到大的顺序自动排序(字母序)

①访问

map<char,int> mp;
mp['a']=100;
// 一、通过下标访问
cout<<mp['a']; //100
// 二、通过迭代器访问
for(map<char,int>::iterator it=mp.begin(); it!=mp.end(); it++)
	printf("%c %d\n", it->first, it->second); //a 100
	// map使用 it->first访问key  it->second访问值

②find()

map<char,int>::iterator it=mp.find('b');
printf("%c %d", it->first, it->second);

③erase()

// 一、删除单个元素
//	法一:mp.erase(it),时间复杂度:O(1)
map<char, int>::iterator it=mp.find('b');
mp.erase(it);
//	法二:mp.erase(key),时间复杂度:O(logN)
mp.erase('b');

// 二、删除一个区间内所有元素
//	mp.erase(first,last),时间复杂度:O(last-first)
map<char,int>::iterator it=mp.find('b');
mp.erase(it,mp.end());

④size() clear()

// 获得“映射的‘对’数”	时间复杂度:O(1)
cout<<mp.size() //若3对,即为3
// 清空,时间复杂度:O(1)
mp.clear();

map常见用途

  • 建立字符(串)与证书之间的映射
  • 判断大整数或其他类型数据是否存在
  • 字符串->字符串的映射
  • 备注:
    map键值唯一,multimap单键对多值
    c++11增加unordered_map,以散列代替红黑树,不用排序



queue

  • 定义
queue<typename> q;
  • 用法/特性
    先进先出

①访问:front() back()

//时间复杂度:O(1)
q.front() //队头
q.back() //队尾

②push() pop()

//时间复杂度:O(1)
q.push(x); //x入队,队尾
q.pop(); //队头出队

③empty() size()

//检测队是否为空,时间复杂度:O(1)
if(q.empty())
//返回queue内元素个数,时间复杂度:O(1)
q.size();

queue常见用途

  • 广度优先搜索,直接调用
  • attention:访问前,先empty()判断是否队空!
  • 同类容器
    • 双端队列(deque)
      首尾皆可插入和删除的队列
    • 优先队列(priority_queue)
      用堆实现的默认将当前队列最大元素置于队首的容器



stack

  • 定义
stack<typename> st;
  • 用法 / 特性
    栈:后进先出

①访问:top() / 出入栈:push(),pop()

//时间复杂度:O(1)
st.push(x); //入栈
x=st.top(); //访问
st.pop(); //出栈

②empty(), size()

//时间复杂度O(1)
if(st.empty()) //判空
st.size() //返回stack内元素个数

stack常见用途

  • 模拟递归,防止“程序对栈内存的限制”而导致出错
    若递归层过深,或导致溢出;用st模拟以避免(较少见)



pair

  • 定义
    两个元素捆绑为“一个合成元素”
#include<utility>
#include<map>	//<map>也含pair,可二选一
struct pair{
	typeName1 first;
	typeName2 second;
};
pair<type1,type2> p;

①构建

pair<string,int> p;
pair<string,int> p("abc",5);
//构建临时pair
pair<string,int>("abc",5); //法一
make_pair("abc",5); //法二

②访问

printf("%s",p.first);
printf("%d",p.second);

③比较大小

先比较first,若相等则再比较second

if(p1<p2)

pair常见用途

  • 替代二元结构体,节约时间
  • 作为map的键值来进行插入
map<string,int> mp;
mp.insert(make_pair("aaa",5));
mp.insert(pair<string,int>("bbb",10));
for(map<string,int>::iterator it=mp.begin(); it!=mp.end(); it++)
	printf("%s %d",it.first,it.second); //it->first, it->second


algorithm

max(), min(), abs(), fabs(), swap()

int x; float xx;
abs(x); //abs()用于“整型”
fabs(xx); //fabs()用于“浮点型”

reverse(a, a+△)

范围 [ it , it + △ )

int a[6]={1,2,3,4,5};
reverse(a,a+3); //3即△,表翻转自‘&a’起的△个元素
// 现在a为{3,2,1,4,5};

next_permutation(a, a+△)

给出一个序列在“全排列”中的“下一个序列”

int a[10]={1,2,3};
do{
	printf("%d%d%d",a[0],a[1],a[2]);
}while(next_permutation(a,a+3));
//结果:123 132 213 231 312 321
```-
--
## fill(a, a+, x)
把数组或容器中的某一段区间赋为某个相同的值
和memset不同,此处“赋值”可为数组类型对应范围中的任意值

```cpp
int a[5]={1,2,3,4,5};
fill(a,a+3,100);
//a为{100,100,100,4,5}

sort()

  • 排序
    不推荐用qsort(设计较多指针,用起来较繁琐)
  • 采用排序方法类似于“快速排序”?时间复杂度:O(n*log2(n))
    规避了经典快速排序中可能的实际复杂度退化到O(n^2)的情况

sort(a, a+△)

默认从小到大排序
char为“字典序”(ASCII)【注意 A < B < a < b】

sort(a, a+△, cmp)

bool cmp(int a, int b) {
	return a > b;
}
int main() {
	int a[4] = { 2,3,1,4 };
	sort(a, a + 4);		// 1 2 3 4
	sort(a, a + 4, cmp);// 4 3 2 1
	return 0;
}

若带结构体

struct node {
	int x, y;
};
struct node {
	int x, y;
};
bool cmp(node a, node b) {
	if (a.x != b.x)
		return a.x > b.x;
	return a.y > b.y;
}

按字符串长度从小到大排序

bool cmp(string str1, string str2){
	return str1.length() < str2.length();
}
  • 注意:STL中只有“vector, string, deque”可使用sort
    因为像set, map元素本身有序(红黑树),不需sort排序

lower_bound() & upper_bound()

  • lower_bound(first, last, val)
    寻找范围内第一个值大于等于val的元素的位置【>=】
    如果是数组,返回该位置 指针
    如果是容器,返回该位置 迭代器

  • upper_bound(first, last, val)
    寻找范围内第一个值大于val的元素的位置【>】

  • 注意:如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!

	int a[10] = { 1,2,2,3,3,3 };
	int* lowerPos1 = lower_bound(a, a + 6, 0);
	int* lowerPos2 = lower_bound(a, a + 6, 2);
	int* upperPos1 = upper_bound(a, a + 6, 2);
	int* upperPos2 = upper_bound(a, a + 6, 3);
	printf("%d,%d,%d,%d", 
	lowerPos1 - a, lowerPos2 - a, upperPos1 - a, upperPos2 - a);

输出结果:0,1,3,6

  • 如只想获取欲查元素下标,也可直接返回地址差值
	cout << upper_bound(a, a + 6, 2) - a;


vector

  • 定义:
    向量(变长数组)
vector<typename> vi;
vector<node> vi;
vector<vector<int>> vi; //二维vector数组

vector<int> vi[100];
  • 访问
    ①下标访问
    ②迭代器访问
vector<typename_>::iterator it;

迭代器(iterator)可以理解为一种类似指针的东西,此it是一个vector<typename_>::iterator型的变量
注意是地址

⓪begin(), end()

vector.begin() :取vector的首元素地址
vector.end() :取尾元素地址的下一个地址

vi[i]
*(vi.begin()+i)
//二式等价

vector<int> vi;
for(vector<int>::iterator it=vi.begin(); it!=vi.end(); it++)
	printf("%d ", *it);

①push_back(), pop_back()

  • push:在vector尾添加,时间复杂度:O(1)
  • pop:删除vector尾元素,时间复杂度:O(1)

②size(), clear()

  • size():
    获取vector元素个数,时间复杂度:O(1)
  • clear():清空vector所有元素,时间复杂度:O(N)
    N为vector中元素的个数

③insert(it, x)

向任意迭代器it(address) 处插入一个元素,时间复杂度:O(N)

//vi={1,2,3}
vi.insert(vi.begin()+2,-1); //将-1插入vi[2]的位置
//vi={1,2,-1,3} 

④erase()

  • erase(it)
    删除迭代器为it 处的元素
//vi={1,2,3,4}
vi.erase(vi.begin()+2)
//vi={1,2,4}
  • erase(first, last)
    删除 [ first, last ) 内的所有元素
//vi={1,2,3,4}
vi.erase(vi.begin(),vi.begin()+2)
//vi={4}

效果上,vi.clear() 与 vi.erase(vi.begin(), bi.end()) 同理

vector常见用途

  • 动态储存数据,动态输入输出
  • 用邻接表存储图



set

  • 定义:集合,是一个内部自动有序不含重复元素的容器
    【自动去重&升序排序】

用迭代器it,通过【it】来访问set里的元素
由于除开vector和string之外的STL容器都不支持
(it+i)的访问方式,所以只能枚举

for(set<int>::iterator it=st.begin();it!=st.end();it++)
	printf("%d", *it);

①insert(x)

将x插入set容器中,并自动递增排序和去重,时间复杂度:O(logN)

②find(val)

返回set中对应值为val的迭代器,时间复杂度:O(logN)

set<int>::iterator it=st.find(2);

③erase()

  • 删除单个元素
    • 删迭代器对应元素
      st.erase(it),时间复杂度O(1)
    • 删值对应元素
      st.erase(value),时间复杂度O(logN)
//利用find()函数找到100,然后用erase删除它
st.erase(st.find(100));
//找value
st.erase(100);
  • 删区间
    st.erase(first, last)
    删除 [ first, last )

④size(), clear()

set常见用途

  • 需要去重但是不方便直接开数组的情况
  • set 元素唯一
    multiset 不唯一
    c++11增加unordered_set,以散列代替set内红黑树实现,只去重但不排序,速度比set快得多



string

  • 定义
string str;
string str="abc123";
  • 访问
//直接访问
cin >> string;
cout << string;
cout << string[i];
printf("%s", str.c_str()); //将string型str使用c_str()变为字符数组

//迭代器访问
for (string::iterator it = str.begin(); it != str.end(); it++)
printf("%c", *it);

string也支持对迭代器加减数字,如str.begin()+2

①加, cmp

str3 = str1 + str2;
str1 += str2;

if(str1 < str2)
if(str1 != str2)
if( str4 >= str2)

length() / size()

时间复杂度O(1),基本相同

②insert()

时间复杂度O(N)

  • insert(pos, string)
    在pos号位置插入字符串string
  • insert(it, it2, it3)
    it为原字符串的欲插入位置,it2和it3为待插字符串的首尾迭代器,用来表示串[it2, it3)将被插在it的位置
s1="abcxyz", s2="123";
s1.insert(3,s2); //法一
s1.insert(s1.begin()+3, s2.begin(), s2.end()); //法二

③erase()

  • 删单个 erase(it)
  • 但区间
    • erase(first, last)
    • erase(pos, len)
      pos为需要开始删除的起始位置,len为删除的字符个数
s = "abc123456"
s.erase(3,3);
//s="abc456"

clear()

substr(pos, len)

返回从pos开始、长度为len的子串,时间复杂度O(len)

s = "Hello World!";
cout << s.substr(0,5); // Hello
cout << s.substr(6,6); // World!

string::npos()

常熟,本身值为-1,但因是unsigned_int类型,可认为是unsinged_int类型最大值
作为find函数失配时的返回值
等于 -1 或者 4294967295

find()

  • s1.find(s2)
    当s2是s1子串时,返回其在s1汇总第一次出现的位置
    若不是,返回string::npos
  • s1.find(s2, pos)
    从s1的pos号位开始匹配s2
    其余同上

时间复杂度:O(nm), n,m分别为s1,s2的长度

s1="abc123123"; s2="123";
cout<<s1.find(s2); // 3
cout<<s1.find(s2,4); // 6

replace()

  • s1.replace(pos, len, s2)
    把s1从pos号位开始、长度为len的子串替换为s2
  • s1.replace(it1, it2, it3)
    把s1的迭代器 [it1, it2) 范围的自传替换为s2

时间复杂度:O(s1.length())

s="abc123"; s2="xyz";
//法一
cout << s.replace(0, 3, s2);
//法二
cout << s.replace(s.begin(), s.begin()+3, s2);
结果:s="xyz123"

参考资料:《算法笔记》

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值