deque 与vector区别

来源:互联网 发布:java 开启多线程任务 编辑:程序博客网 时间:2024/05/15 23:03

原文引用自 http://www.yesky.com/100/1889600.shtml

什么是新的?


  细读上面两张表格,你会发现和vector比较这里增加了两个函数。

  1、c.push_front(elem) —— 在头部插入一个数据。

  2、c.pop_front() —— 删除头部数据。

  调用方法和c.push_back(elem)和c.pop_back()相同,这些将来会告诉我们对于deque> 会非常有用,deque可以在前后加入数据。>

  缺少了什么?

  同时你也会发现相对于vector> 缺少了两个函数,你将了解到deque> 不需要它们。

  1、capacity()—— 返回vector当前的容量。

  2、reserve() —— 给指定大小的vector> 分配空间。

也就是加了俩东西,删掉的平常也很少用,先不管。

加了头插和头删,如果有这种需求的可以deque,之前碰到mergeinterval之类的题时,很多都是中间删除,因此deque也还是不起作用,所以还是用linklist来做

这样借助vector又对deque熟练起来.另外vector的erase操作一定要及时获取iterator,因为删除掉一个元素后,如果还是正常的循环后移,会多移一个元素。

另外查阅cplusplus,list是基于双项链表实现的,所以支持高校插入删除,不支持高校随机存取。与vector的区别就理解为vector和list的区别了。

另外今天还稍微用了下STL的map,犹记得当年质量极差的代码算precision recall 的时候,fawks大神说为啥不用map,包括廖师兄大神的python也是map= =   这个特别适合算这种有重复的的东西,例如wordcount有大量的查找,简单说是每次新来的词都要查,因此查找效率很重要,map底层是红黑树实现,O(logn)的时间复杂度,因此已经不错了,先把更好的hash搁置一下。而且里面插入特别方便,直接访问key就行了,如果找得到的话,是对应的key的value赋值。其实也提供了insert,但是不方便,不如直接[] 就插入了。理解这个key value 一直挺别扭,好像很多都有,hash,mapreduced,是通过数据库的PK来理解的,然后通过key不能重复,value是另外的一个可以重复的属性。find操作找不到返回end() 的迭代器。赋上wordcount的代码:

#include <iostream>#include <sstream>#include <fstream>#include <vector>#include <map>#include <string>using namespace std;int main(){ifstream fin("E:\\VisualStudioWorkspace\\LeetCode\\UniqueBinaryTree\\Debug\\01BagInput.txt");if(fin==NULL) return -1;string line,splitword;map<int,int> wordcount; while(getline(fin,line,'\n')){istringstream istr(line);while(istr>>splitword){int splitnum=atoi(splitword.c_str());if(wordcount.find(splitnum)!=wordcount.end())wordcount[splitnum]++;elsewordcount[splitnum]=1;}}for(map<int,int>::iterator it=wordcount.begin();it!=wordcount.end();it++){cout<<it->first<<" "<<it->second<<endl;}return 0;}

由于红黑树的优良查找性能,插入性能,如果有n个词,时间复杂度应该是log1+...+logn-1(插入或者查找选一个,每次都是logn),之前算过上界是nlogn 所以O(nlogn) 比一般的n^2要好

后来突然发现hash_map 不是C++标准的,而我却可以用,才发现一直用的MS的lib,好像和STL 还是cplusplus的说明很像。。

附上map和hash_map的用法,发现hash居然几次测试比map慢,是因为hash函数不好,导致collision太多的原因么?

#include <iostream>#include <sstream>#include <fstream>#include <vector>#include <map>#include <hash_map>#include <string>#include <ctime>using namespace std;void hashmap_wordcount(){ifstream fin("E:\\2013-03-08-NTUInternship\\MetaSLForHuman\\Data\\PositiveSLAllFeatures.txt");if(fin==NULL) return ;string line,splitword;hash_map<string,int> wordcount; while(getline(fin,line,'\n')){istringstream istr(line);while(istr>>splitword){//int splitnum=atoi(splitword.c_str());hash_map<string,int>::iterator it=wordcount.begin();if((it=wordcount.find(splitword))!=wordcount.end())//wordcount[splitword]++;it->second++;else//wordcount[splitword]=1; wordcount.insert(make_pair<string,int>(splitword,1));}}/*for(hash_map<string,int>::iterator it=wordcount.begin();it!=wordcount.end();it++){cout<<it->first<<" "<<it->second<<endl;}*/}void map_wordcount(){ifstream fin("E:\\2013-03-08-NTUInternship\\MetaSLForHuman\\Data\\PositiveSLAllFeatures.txt");if(fin==NULL) return ;string line,splitword;map<string,int> wordcount; while(getline(fin,line,'\n')){istringstream istr(line);while(istr>>splitword){//int splitnum=atoi(splitword.c_str());map<string,int>::iterator it=wordcount.begin();if((it=wordcount.find(splitword))!=wordcount.end())it->second++;else//wordcount[splitword]=1;wordcount.insert(make_pair<string,int>(splitword,1));}}/*for(map<string,int>::iterator it=wordcount.begin();it!=wordcount.end();it++){cout<<it->first<<" "<<it->second<<endl;}*/}int main(){clock_t start,finish;start=clock();map_wordcount();finish=clock();cout<<(double)(finish-start)/CLOCKS_PER_SEC<<endl;start=clock();hashmap_wordcount();finish=clock();cout<<(double)(finish-start)/CLOCKS_PER_SEC;return 0;}


借此总结一下代码实现算法数据结构问题的思路:

1. 想出尽可能多的解法,从简单的开始逐步优化,直至确定要实现的算法

2.设计框架,一块写一个注释模块,记录灵光一现的变量设计和处理

3.coding实现展开模块

4.判断输入数据各个边界条件,0 NULL 等

5.判断程序边界条件,数组,字符串访问上下越界,指针访问是否NULL,stack做pop()是否空,然后指针式从下到上逐个处理是否可能出现exception,要单独处理这些case或者可以统一起来


今天看到一道面试题,挺有意思:

递归函数最终会结束,那么这个函数一定(不定项)

1:使用了局部变量;
2:有一个分支不调用自身;
3:使用了全局变量或者使用了一个或多个参数;
2是对的,如果没有出口的,话就是无穷递归了,感觉3也是对的,因为递归要朝着小的方向推进,1不对,阶乘就可以推翻,可能有人觉得return n*f(n-1) 中n也是局部变量,那么直接return f(n-1), 
虽然函数没有太大意义。但是答案说3居然是错的,说有异常终止,感觉好牵强啊。。。如果这样的话我不设置递归出口,然后一直自身调用,最后栈溢出了,也异常结束了。。。


另外看到变量根据作用域类型分类,局部自动变量用的最多,auto可省略,以致大家都忽视了局部自动变量的存在,而看到了静态局部变量,于是想到可以考虑和递归结合起来,因为时间全局,一个函数可访问,刚好符合递归特性,这样一个值可以一直保存下来,以后设计递归程序有疑惑的时候就采用这种机制试试。

0 0
原创粉丝点击