关于合理选择数据结构解题的一些总结
Posted 花落,莫相离
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于合理选择数据结构解题的一些总结相关的知识,希望对你有一定的参考价值。
在解题时,合理地选择数据结构可真是太重要了,选择合理不仅使操作简单,更不易把自己搞晕。下面进行适当总结:
1.使用STL容器虽然看上去很高级,有时也能简化一些操作、节省内存等,但不要什么都想用STL容器来解决,因为静态数组更容易操作,且有时比STL容器省空间省时间(访问快,除非特殊情况,比map省空间)
2.数据结构不要套太多娃,也即开的结构体不要太复杂,一层套一层,最后把自己搞晕,最多套一层(比如嵌入另一个结构体,或开一个数组,放一个STL啥的)。若有需要,单开结构体或数组啥的,建立一个映射即可,操作会清晰简单很多,也没有占多大内存。
常见STL用法梳理:
vector
1.insert():向指定位置处插入元素
erase():删除单个元素或者一个区间内的所有元素
以上两个操作参数均为迭代器。
2.begin()、rbegin()、end():分别为第一个元素、最后一个元素、以及尾元素的下一个地址。
3.可以直接判等,直接比较。
4.整体赋值:
vector<int> temp(inDegree, inDegree+N); //这种用法留意一下,即将inDegree数组的从0到N-1的全部元素整体赋值给temp
5.拓展应用:
vector<int> v;
//栈
v.erase(--v.end());
v.erase(v.rbegin());
v.pop_back();
//队列
v.erase(v.begin());
//双端队列
v.insert(v.begin(), 1);
set
自动去重并按升序排序。
string
1.insert():
insert(pos, string) insert(it, it1, it2)
2.erase():
erase(it) erase(first, last) erase(pos, len)
3.substr():
substr(pos, len)
4.find():(注意结合string::npos使用)
find(str) find(str, pos)
5.replace():
replace(pos, len, str) replace(it1, it2, str)
6.sscanf() sprintf():
虽然不是string所特有的函数,但是结合使用效果很棒(注意使用时结合c_str()函数才能用)
priority_queue
优先队列设置结构体优先级时队首元素与一般cmp表示的意义相反。
优先队列默认队首元素最大,若修改为最小,即:priority_queue<int, vector<int>, greater<int> > q
下面是结构体优先级设置的一些方法,一般可以结合priority_queue和set使用。
struct node{
int x, y;
friend bool operator < (node a, node b){
return a.x < b.x;
}
};
struct node{
int x, y;
friend bool operator < (const node &a, const node &b){
return a.x < b.x;
}
};
struct node{
int x, y;
friend bool operator < (const node &b) const{
return x < b.x;
}
};
algorithm
1.lower_bound,upper_bound:
用于有序数组或容器中。int* pos = lower_bound(first, last, val)
int* pos = upper_bound(first, last, val)
形参为指针或迭代器。分别用来寻找第一个值大于等于val和大于val的元素的位置,返回一个指针或迭代器。
2.heap:
make_heap: 根据指定的迭代器区间以及一个可选的比较函数,来创建一个heap。O(N)
push_heap: 把指定区间的最后一个元素插入到heap中。O(logN)
pop_heap: 弹出heap顶元素, 将其放置于区间末尾。O(logN)
sort_heap:堆排序算法,通常通过反复调用pop_heap来实现。N*O(logN)
is_heap: 判断给定区间是否是一个heap。O(N)
is_heap_until: 找出区间中第一个不满足heap条件的位置。O(N)
vector<int> v{6, 1, 2, 5, 3, 4};
//进行堆的相关操作之前记得先建堆,且注意后面堆的所有操作都默认是大根堆,若想使用小根堆必须添加比较函数
//默认建立大根堆
make_heap(v.begin(), v.end());
//建立小根堆,仅给出这一示范,下面使用小根堆时类似
make_heap(v.begin(), v.end(), greater<int>());
//插入堆
v.push_back(200);
push_heap(v.begin(), v.end());
//堆顶元素出堆,置于堆末尾
pop_heap(v.begin(), v.end());
v.pop_back();
//堆排序
sort_heap(v.begin(), v.end());
//判断是否是堆
is_heap(v.begin(), v.end());
//返回第一个不是堆元素的迭代器
auto it = is_heap_until(v.begin(), v.end());
注意:
只有在vector和string中,才能对迭代器直接加整数来处理
只有vector和string可以通过下标访问,其他只能通过迭代器访问
顺序存储 or 散列存储:一般当需要访问特定id对应的数值只有一个,或只关注是否存在时,使用顺序存储,并单独开辟一个简单的散列数组(或者map)来建立这种单一映射关系。但若特定id对应多个数值甚至是复杂的数据结构时,则考虑使用散列存储,直接将全部信息存储在下标为其id处,从而便于访问与修改信息。
关于数组 or map:一般更推荐使用数组,除非那种字符串不好使用数组,或二维甚至三维信息建立映射使用数组会占用大量使用不到的内存时,才去使用map。并且注意,map是很占内存的,故尽量少使用。并且主要用来建立映射关系,不要把它当做散列存储工具,散列存储还是更多用数组。
以上是关于关于合理选择数据结构解题的一些总结的主要内容,如果未能解决你的问题,请参考以下文章