一、对标准库中的list介绍
list是可以在常数范围内 在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代 。 list的底层是双向链表 结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。 list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问 ,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)
注意 : list的迭代器是双向迭代器 ,vector的迭代器是随机迭代器 ,主要区别在于双向迭代器不支持+- 操作 正由于list的双向迭代器,因此<algorithm>
中的sort()
函数无法使用,list单独实现了一个sort()函数,但效率极低。不建议使用
二、list的使用
2.1 list的构造函数
构造函数声明 接口说明 list() 无参构造 list(size_type n, const value_type& val ) 构造并初始化n个val list (const list& x); 拷贝构造 list (InputIterator first, InputIterator last); 使用迭代器进行初始化构造
void test1 ( )
{ list< int > l1; list< int > l2 ( 5 , 0 ) ; list< int > l3 = l2; list< int > l4 ( l2. begin ( ) , l2. end ( ) ) ;
}
2.2 list的迭代器访问
此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点
iterator的说明 接口说明 begin()+end() 获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator rbegin()+rend() 获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator
void test2 ( )
{ list< int > l1 = { 0 , 1 , 2 , 3 , 4 , 5 , 6 } ; auto it1 = l1. begin ( ) ; while ( it1 != l1. end ( ) ) { cout << * it1 << " " ; it1++ ; } cout << endl; auto it2 = l1. rbegin ( ) ; while ( it2 != l1. rend ( ) ) { cout << * it2 << " " ; it2++ ; } cout << endl;
}
注意:
begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动 rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动
2.3 list的容量操作
容量空间 接口说明 size() 获取数据个数 empty() 判断是否为空
void test3 ( )
{ list< int > l1 = { 0 , 1 , 2 , 3 , 4 , 5 , 6 } ; cout << "size:" << l1. size ( ) << endl; cout << "Is_Empty:" << l1. empty ( ) << endl;
}
2.4 list的增删查改
操作 接口说明 push_front() 头插 pop_front() 头删 push_back() 尾插 pop_back () 尾删 insert() 在pos之前插入val erase() 删除pos位置的数据 swap() 交换两个list的数据空间 clear() 清空容器
void test4 ( )
{ list< int > l1 = { 0 , 1 , 2 , 3 , 4 , 5 , 6 } ; list< int > l2; for ( auto & e : l1) cout << e << " " ; cout << endl; l1. push_front ( 100 ) ; l1. push_back ( 200 ) ; l1. push_back ( 300 ) ; for ( auto & e : l1) cout << e << " " ; cout << endl; l1. pop_front ( ) ; l1. pop_back ( ) ; for ( auto & e : l1) cout << e << " " ; cout << endl; l1. insert ( l1. begin ( ) , 400 ) ; for ( auto & e : l1) cout << e << " " ; cout << endl; l1. erase ( l1. begin ( ) ) ; for ( auto & e : l1) cout << e << " " ; cout << endl; l1. swap ( l2) ; l2. clear ( ) ;
}
2.5 list的元素获取
操作 接口说明 front() 取第一个元素 back() 取最后一个元素
void test5 ( )
{ list< int > l1 = { 0 , 1 , 2 , 3 , 4 , 5 , 6 } ; cout << "front:" << l1. front ( ) << endl; cout << "back:" << l1. back ( ) << endl;
}
2.6 list的其他操作
操作 接口说明 void splice (const_iterator position, list& x); 把x中所有元素转移到position位置之前 void splice (const_iterator position, list& x, const_iterator i); 仅仅把x中i位置的元素转移到position位置之前 void splice (const_iterator position, list& x,const_iterator first, const_iterator last); 把x中[first,last)区间的元素转移到position位置之前 void remove (const value_type& val); 移除val,这个和erase差不多 void unique(); 去重操作,必须是有序序列才能进行此操作 void merge (list& x) 对两个链表进行归并排序 void sort(); 对链表进行排序,底层不是快排,可能是归并 void reverse() 链表逆置