标签:des style blog io color ar os sp for
Leetcode更新到155题了,这个easy的题acceptance却不高,我好奇的点开了它。
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
果然easy嘛,そして:
class MinStack { struct node { int value; node * next; node(int v, node * n=0):value(v),next(n){} }; node * h; node * min; public: MinStack():h(0), min(0){} void push(int x) { h = new node (x, h); if(!min || min->value >= x) min = new node (x, min); } void pop() { if(h) { node * p; if(h->value == min->value) { p = min; min = min->next; delete p; } p = h; h = h->next; delete p; } } int top() { if(h) return h->value; throw; } int getMin() { if(min) return min->value; throw; } };
据说通用的STL容器非常多虑,多线程神马的都考虑了进去,静态链接也会把从来不调用的函数加进去,因此我习惯于手动实现容器。XX怎么回事:memory limited error!N个next指针居然就不耐了也太傲娇了!
那么不用链式结构了,改用数组吧。就用vector试试。
class MinStack { vector<int> h; vector<int> min; public: void push(int x) { h.push_back(x); if (min.empty() || min.back() >= x) min.push_back(x); } void pop() { if (h.back() == min.back()) min.pop_back(); h.pop_back(); } int top() { return h.back(); } int getMin() { return min.back(); } };
XX,又是mle!最后看到别人用deque,做法大同小异,就抄了过来。好在STL里的函数名称比较统一,vector和deque的抽插都叫做push_back和pop_back,改下定义就好啦:
class MinStack { deque<int> h; deque<int> min; public: void push(int x) { h.push_back(x); if(min.empty() || min.back() >= x) min.push_back(x); } void pop() { if(h.back() == min.back()) min.pop_back(); h.pop_back(); } int top() { return h.back(); } int getMin() { return min.back(); } };
查了下资料,又涨知识了!deque采用数组和链表的这种策略,初始先分配一块连续内存,不够了再分配一块,然后这些先后分配的内存通过指针“通通连起来”,逻辑上就是连续的空间了。这种东西早就想写一个,没想到STL已经提供了,而且STL中的stack和queue等容器底下正是它!perfect!
现在比较下数组、vector和deque:
1:原理:
数组:连续且固定的空间;
vector:连续但不固定的空间,原空间不够了将会调用allocator进行realloc,然后通过uninitialized_copy复制旧内容。
deque:连续的链式空间,空间不够则分配新的空间,每个内存块呈链式(不是新鲜事吧?从前学数据结构,有这样实现过string,学操作系统,其中文件管理也有用链式方法的)。
2:增长方向:
数组:长不大
vector:逻辑上是ForwardIncremental的
deque:显然是双向的了。
3:性能:
用下面这段简单的代码测试下,因为我用的是上上个五年计划的时候出的Thinkpad X61,N=100000000,sizeof(x
) = 12B差不多是极限了。
用int测试时,输出4 6;
用struct测试时,deque的循环输出7,vector在插入过程中直接bad_alloc,原因是找不到足够大的连续内存了。
#include <cstdlib> #include <ctime> #include <deque> #include <vector> #include <iostream> using namespace std; struct s { int v; int a[2]; s(int i):v(i){} ~s() { //make it a non-trivial destructor; } }; main() { typedef s T; int const N = 100000000; int i; double start; deque<T> d; vector<T> v; start = time(0); for(i=0; i<N; i++) d.push_back(T(i)); for(i=0; i<N; i++) d.pop_back(); cout <<time(0) - start<<endl; start = time(0); for(i=0; i<N; i++) v.push_back(T(i)); for(i=0; i<N; i++) v.pop_back(); cout <<time(0) - start<<endl; }
当然并非以后就弃vector不用了,如果每次访问的内存地址比较跳跃,deque的效率必然就不行了,因为要跳到另一个块上,it++当然不行,至少需要访问两次内存了。果然存在即有理。
标签:des style blog io color ar os sp for
原文地址:http://www.cnblogs.com/zhchngzng/p/4097798.html