STL中map与优先级队列

先说说STL的容器一些常见的注意问题:有网友说,为什么用了STL,程序的效率反而下降了呢?是的,如果用不好,你编程是方便了,可是效率下降了. 1: Vector,这个是基于线性数组的容器 注意事项: 在声明一个vector的时候,尽量指明大小,如果输入数据不超过10^6,那就声明一个10^6大小的vector,否则,vector的默认大小是10.(太小了),但是vector的大小可以自动扩大,不要以为仅仅是在已经分配的空间后面再多申请一块,而是新开辟一块空间,把原来的复制过去.想一下,如果你的vector不断的扩容,不断的复制,效率能不低吗?这就是有的网友问为什么STL的vector没有数组的效率高的原因. 2: Set, Map, 都是基于RB-Tree的容器,所以有自动排序功能 插入删除,查找效率都很高,查找1000个记录,最多查找10次,查找1000000个记录,最多查找20次 注意事项: 许多人喜欢用,但是如果频繁的插入,删除,不建议使用.因为每插入一次或者删除一次,都要对RB-tree进行一次调整,n次插入,时间复杂度nlgn. 但是如果插入,删除不频繁的情况下是首选. 3: hash_set, hash_map, 都是基于hash_table的,没有自动排序功能 注意事项: 在声明的时候也要尽量指明大小,否则哈希表的容量达到thresh_hold的时候要自动扩容,所有元素再哈希一次.时间不容忽视. hash_table默认初始大小53, 然后扩容至97,193,389,故意是质数.默认的是朴素哈希函数:比如"apple"的hash code: 5*(5*5*(5*'a'+'p')+'p')+'l')+'e' % 53 = 78066%53 = 50 目前hash_set hash_map都已经不再是标准的容器,namespace也从std move to stdext. Linux下名字空间是__gnu_cxx. (不推荐使用) 4: list: 双向链表,内存空间不连续 只能用remove,remove_if, erase来删除,inset插入,不可以直接修改pre,next.插入删除效率比较高 5: deque 双端队列 分段连续内存空间,可以遍历(提供iterator) 6: stack,queue 栈和队列,唯一注意的是选择底层容器,默认是deque,可以选择list,vector,根据插入,删除情况选择合适的容器.(不同的底层容器扩容时带来的效率影响), 二者均不提供iterator 7: priority_queue 优先级队列 (STL里面最笨拙的容器) 基于堆,默认是大根堆,可以在构造函数里面提供自己的比较函数实现小根堆. 不提供遍历,不能查找,不能修改里面的元素,只提供top,push,pop 用A*搜索的朋友注意了,添加新的子节点到openlist时,要判断是否有重复节点,修改F值,这时才能体会到这个容器的笨拙之处. 8: Algorithm里面提供了make_heap, push_heap, pop_heap, 如果单纯做搜索,能不用就不用了吧,pop_heap并没有把元素弹出,而是放到了末尾. 适合对一个未排序的数组进行堆排序使用. 其实我想说的是如果我们真的需要一个优先级队列,前提是我们能对这个优先级队列查找,遍历,修改(当然修改优先级之后能自动排序),那就用map或者set来做吧.(取决于你要存储的数据,前者是key,value对,后者只有key). 举例如下: view plaincopy to clipboardprint? map> m; //最小的永远处于前面 m[8] = 10; m[3] = 9; m[9] = 8; m[1] = 22; for(map>::const_iterator itor = m.begin();itor != m.end();itor++) printf("%d/n",itor->first); //输出 1 3 8 9 m[5] = 100; for(map>::const_iterator itor = m.begin();itor != m.end();itor++) printf("%d/n",itor->first); //输出 1 3 5 8 9 map> m; //最小的永远处于前面 m[8] = 10; m[3] = 9; m[9] = 8; m[1] = 22; for(map>::const_iterator itor = m.begin();itor != m.end();itor++) printf("%d/n",itor->first); //输出 1 3 8 9 m[5] = 100; for(map>::const_iterator itor = m.begin();itor != m.end();itor++) printf("%d/n",itor->first); //输出 1 3 5 8 9 如果要修改优先级怎么办呢? 反正修改之后也要对RB_tree进行调整,那就先remove掉,再放进一个新的,比如上面的例子我要把m[5]的优先级改为10,可以如下方式: (注意,不可以直接修改key,map的iterator提供的key是只读的,也就是说itor->first是const的) view plaincopy to clipboardprint? int value = m[5]; m.erase(5); m[10] = value; for(map>::const_iterator itor = m.begin();itor != m.end();itor++) printf("%d/n",itor->first); //输出 1 3 8 9 10 int value = m[5]; m.erase(5); m[10] = value; for(map>::const_iterator itor = m.begin();itor != m.end();itor++) printf("%d/n",itor->first); //输出 1 3 8 9 10 以上是自己对STL做个小小的总结。 下面总结下STL中priority_queue的用法 在优先队列中,优先级高的元素先出队列。标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。优先队列的第一种用法,也是最常用的用法: view plaincopy to clipboardprint? priority_queue qi; priority_queue qi; 通过<操作符可知在整数中元素大的优先级高。故示例1中输出结果为:9 6 5 3 2 第二种方法:在示例1中,如果我们要把元素从小到大输出怎么办呢?这时我们可以传入一个比较函数,使用functional.h函数对象作为比较函数。 view plaincopy to clipboardprint? priority_queue, greater >qi2; priority_queue, greater >qi2; 其中第二个参数为容器类型。第二个参数为比较函数。故示例2中输出结果为:2 3 5 6 9 第三种方法:自定义优先级。 view plaincopy to clipboardprint? struct node { friend bool operator< (node n1, node n2) { return n1.priority < n2.priority; } int priority; int value; }; struct node { friend bool operator< (node n1, node n2) { return n1.priority < n2.priority; } int priority; int value; }; 在该结构中,value为值,priority为优先级。通过自定义operator<操作符来比较元素中的优先级。在示例3中输出结果为:优先级 值 9 5 8 2 6 1 2 3 1 4 但如果结构定义如下: view plaincopy to clipboardprint? struct node { friend bool operator> (node n1, node n2) { return n1.priority > n2.priority; } int priority; int value; }; struct node { friend bool operator> (node n1, node n2) { return n1.priority > n2.priority; } int priority; int value; }; 则会编译不过(G++编译器)因为标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。而且自定义类型的<操作符与>操作符并无直接联系,故会编译不过。 //代码清单 view plaincopy to clipboardprint? #include #include #include using Namespace stdnamespace std; struct node { friend bool operator< (node n1, node n2) { return n1.priority < n2.priority; } int priority; int value; }; int main() { const int len = 5; int i; int a[len] = {3,5,9,6,2}; //示例1 priority_queue qi; for(i = 0; i < len; i++) qi.push(a[i]); for(i = 0; i < len; i++) { cout<

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值