用map做优先级队列 (众多ACMers, 一定要熟悉STL)(转)

先说说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).

举例如下:
    map<int,int,less<int>> m; //最小的永远处于前面
    m[8] = 10;
    m[3] = 9;
    m[9] = 8;
    m[1] = 22;

    for(map<int,int,less<int>>::const_iterator itor = m.begin();itor != m.end();itor++)
        printf("%d/n",itor->first);

   //输出 1 3 8 9 

    m[5] = 100;
    for(map<int,int,less<int>>::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的)

    int value = m[5];
    m.erase(5);
    m[10] = value;
    for(map<int,int,less<int>>::const_iterator itor = m.begin();itor != m.end();itor++)
        printf("%d/n",itor->first);
    //输出 1 3 8 9 10   

以上是自己对STL做个小小的总结。

http://hi.baidu.com/azuryy/blog/item/8ec53e118dd945c3a7ef3f30.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值