问题描述:
1个容器有大量元素,需要进行erase大部分数据的时候,需要遍历这些元素,然后释放item的空间,还要erase删除其item。
一个库,为了测试其性能的时候,需要保存所有外部使用者的数据,这里选取了map,vector和list.
为了简化问题,我写了下面测试代码来测试各个操作:
数据节点:
struct node


{

node(int i)
{data = i;}
int data;
}
1
int _tmain(int argc, _TCHAR* argv[])
2

{
3
typedef std::map<long,node*> Mptable;
4
typedef std::vector<node*> Vec;
5
typedef std::list<node*> List;
6
7
Mptable mapnode;
8
Vec vecnode;
9
List listnode;
10
11
for(int i = 1 ; i <= 100000 ; i++ )
12
{
13
mapnode [ i ] = new node(i);
14
vecnode.push_back( new node(i) );
15
listnode.push_back( new node(i));
16
}
17
18
long time = timeGetTime( );
19
20
for( Mptable::iterator itr = mapnode.begin() ; itr != mapnode.end() ; )
21
{
22
delete itr->second;
23
mapnode.erase( itr++ );
24
}
25
26
std::cout <<"map : spend " << timeGetTime() - time << " msec " << std::endl;
27
28
29
time = timeGetTime( );
30
31
for( Vec::iterator itr = vecnode.begin() ; itr != vecnode.end() ; )
32
{
33
delete *itr;
34
itr = vecnode.erase( itr );
35
}
36
37
std::cout <<"vector : spend " << timeGetTime() - time << " msec " << std::endl;
38
39
40
time = timeGetTime( );
41
42
for( List::iterator itr = listnode.begin() ; itr != listnode.end() ; )
43
{
44
delete *itr;
45
itr = listnode.erase( itr );
46
}
47
48
std::cout <<"list : spend " << timeGetTime() - time << " msec" << std::endl;
49
50
51
return 0;
52
}
Release下运行结果:
map : spend 31 msec
vector : spend 3734 msec
list : spend 35 msec
发现map的速度最快,vector最慢,list相当。
其实vector就是一个Array,只是Array是静态大小,vector可以扩展,然后查看vector的erase的源码:
iterator erase(const_iterator _Where)

{ // erase element at where
_Move(_VIPTR(_Where) + 1, this->_Mylast,
_VIPTR(_Where));
_Destroy(this->_Mylast - 1, this->_Mylast);
--this->_Mylast;
return (_Make_iter(_Where));
}
有一个move操作,原来把当前iterator+1的往前移了,这样的话会遍历iterator后面所有的元素。
关于map的erase原理可以查看map的实现源码:
由于map的erase后有一个维护过程,其实map是一个RB-Tree,删除算法相对比较麻烦,删除某个item会查找下一个item替换删除的节点,同时还要考虑红和黑的节点处理。同时还要保证map的erase后,平衡且有序。
所以map的erase主要做:
1.刪除item.
2.让树平衡,且有序。
list其实是一个双向链表:
关于删除其实是0(1)的操作,我们查看list的erase的操作:
iterator erase(const_iterator _Where)

{ // erase element at _Where
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Where._Getcont() != this || _Where._Ptr == this->_Myhead)
_DEBUG_ERROR("list erase iterator outside range");
_Nodeptr _Pnode = (_Where++)._Mynode();
_Orphan_ptr(*this, _Pnode);

#else /* _ITERATOR_DEBUG_LEVEL == 2 */
_Nodeptr _Pnode = (_Where++)._Mynode();
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */

if (_Pnode != this->_Myhead)

{ // not list head, safe to erase
this->_Nextnode(this->_Prevnode(_Pnode)) =
this->_Nextnode(_Pnode);
this->_Prevnode(this->_Nextnode(_Pnode)) =
this->_Prevnode(_Pnode);

_Dest_val(this->_Alnod, _Pnode);
this->_Alnod.deallocate(_Pnode, 1);

--this->_Mysize;
}
return (_Make_iter(_Where));
}
主要代码删除就是下面删除部分:
对prev和next节点进行处理即可。
关于list的移除竟然比map还要慢.
PS:测试为单线程。
当为100W数据的时候:
map : spend 300 msec
list : spend 385 msec
咋list比map容器还要慢?
还是上面的代码不能说明问题。