前言
本文的整理针对平常做算法题比较常用的数据结构和操作,并不适用于平常工程或项目。
大部分算法题涉及到的数据结构并不复杂,所以本文整理的数据结构都是比较基础的操作,适合忘记怎么操作的时候看一眼。
根据做题情况持续更新中…
vector-动态数组
定义在头文件 vector
中
初始化:
vector<type> vec
:无元素,此时访问会越界vector<type> vec(n)
:创建n
个默认初始化的元素vector<type> vec(n, val)
:创建n
个值为val
的元素
常用操作:
vec.size()
:返回数组大小vec.clear()
:清空数组vec.push_back(val)
:在数组最后插入一个元素val
vec.pop_back()
:删除最后一个元素vec[index]
:通过下标访问元素vec.front()
:第一个元素vec.back()
:最后一个元素(常用于模拟栈)
其他操作:i
从0开始
vec.insert(vec.begin() + i, val)
:在第i
个元素前插入val
vec.erase(vec.begin() + i)
:删除第i
个元素
map-哈希表
map
和 unordered_map
分别定义在头文件 map
和 unordered_map
中,其中又细分出 multimap
和 unordered_multimap
。
区别如下:
map
:底层存储是有序的,维护有序需要一定的性能开销unordered_map
:底层存储无序multimap
:可以出现重复关键字的map
unordered_multimap
:可以出现重复关键字的unordered_map
操作几乎没有区别,以下以 map
举例。
初始化:
map<type1, type2> hashTable
:通过hashTable[type1Val]
访问到type2Val
常用操作:
hashTable.find(key)
:如果没有键key
,返回hashTable.end()
,否则返回其迭代器hashTable[key] = val
:如果存在 key 为val
的元素,修改其值,否则创建一个 key 为key
值为val
的元素hashTable.erase(key)
:移除键为 key 的元素
遍历:
//e 类型为 pair<type1, type2>&
for(auto& e : hashTable){
//e.first为 key,e.second 为其值
e.second = val;
}
set-集合
set
和 unordered_set
分别定义在头文件 set
和 unordered_set
中,其中又细分出 multiset
和 unordered_multiset
。
区别如下:
set
:底层存储是有序的,维护有序需要一定的性能开销unordered_set
:底层存储无序multiset
:可以出现重复关键字的set
unordered_multiset
:可以出现重复关键字的unordered_set
操作几乎没有区别,以下以 set
举例。
初始化:
set<type> s
:创建一个集合s
常用操作:
s.insert(val)
:插入一个值为val
的元素s.count(val)
:返回值val
的计数s.erase(val)
:删除元素val
stack-栈
stack
定义在头文件stack
中。
初始化:
stack<type> s
:创建一个空栈s
常用操作:
s.empty()
:栈空返回真s.push(val)
:将val
压入栈s.top()
:返回栈顶元素,不删除s.pop()
:弹出栈顶元素,没有返回值s.size()
:返回栈大小s = stack<type>()
:通常用于清空栈
queue-队列
queue
定义在头文件 queue
中,deque
定义在头文件 deque
中。
queue
为一般队列,一边进另一边出。
deque
为双端队列,两边都可进或出。
priority_queue
为优先队列,是有序的。
初始化:
queue<type> q
:创建一个空队列q
deque<type> dq
:创建一个空双端队列dq
priority_queue<type>
:默认是大顶堆,队首元素最大。priority_queue<type, vector<type>, greater<int>>
:小顶堆,队首元素最小。其中第二个参数vector<type>
代表底层存储容器,greater<int>
为比较器,可以自定义。
queue
操作:
q.front()
:返回第一个元素(最早插入的),不删除q.back()
:返回最后一个元素(最近插入的),不删除q.push(val)
:压入一个元素val
q.pop()
:弹出第一个元素
deque
操作:
dq.push_back(val)
:在后端压入一个元素val
dq.push_front(val)
:在前端压入一个元素val
dq.pop_back()
:弹出最后端的元素dq.pop_front()
:弹出最前端的元素dq.front()
:返回最前端的元素,不删除dq.back()
:返回最后端的元素,不删除
priority_queue
操作:同上,只不过不同的是 push
后,元素的位置是不确定的,根据大小会自己找到一个合适的位置。而 pop
只会弹出堆顶元素。
自定义排序:通过重载 ()
运算符
template <typename T>
struct Compare {
bool operator()(T a, T b) {
return a < b; // 大顶堆
return a > b; // 小顶堆
}
};
// 声明
std::priority_queue<int, std::vector<int>, Compare<int>> pq;
// 也可以通过 lambda 表达式
auto compare = [](int a, int b) {
return a < b; // 大顶堆
return a > b; // 小顶堆
};
// 声明
std::priority_queue<int, std::vector<int>, decltype(compare)> pq(compare);
sort
对于自定义的比较器,当比较器返回 true
时,第一个参数放在前面,第二个参数放在后面,即位置不变,当比较器返回 false
时,为两元素交换位置。
自定义比较器:
vector<int> vec{1, 2, 3, 5, 4};
std::sort(vec.begin(), vec.end(), [](int a, int b) {
return a < b; // 按升序排序
return a > b; // 按降序排序
});
字符串
字符判断:参数为 char
isdigit()
:判断是否为数字isalpha()
:判断是否为字母(不区分大小写)isupper()
:判断是否为大写字母islower()
:判断是否为小写字母isalnum()
:判断是否为字母和数字toupper()
:将字母转化为大写tolower()
:将字母转化为小写
查找子串:str.find("something", idx)
:返回子串第一个字符的下标,idx
为开始寻找的起始下标
替代子串:str.replace(idx, len, str2)
:从 idx
开始,替换成 str2
,长度为 len
,如果 len
短于 str2.size()
,则取 str2
的部分,过长则可能溢出
获取子串:str.substr(idx, len)
:从 idx
开始获取长度为 len
的子串
数字转化:
stoi(str)
、stol(str)
、stoll(str)
:将字符串转化为整数(int
、long
、long long
)stof(str)
、stod(str)
:将字符串转化为浮点数(float
、double
)to_string(num)
:将数字转化为字符串
字符串分割:
// 根据 delimiter 将字符串分为多个子串
std::vector<std::string> split(const std::string &s, char delimiter) {
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(s);
while (std::getline(tokenStream, token, delimiter)) {
tokens.push_back(token);
}
return tokens;
}