deque 与vector区别

原文引用自 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]++;
			else
				wordcount[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可省略,以致大家都忽视了局部自动变量的存在,而看到了静态局部变量,于是想到可以考虑和递归结合起来,因为时间全局,一个函数可访问,刚好符合递归特性,这样一个值可以一直保存下来,以后设计递归程序有疑惑的时候就采用这种机制试试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值