深入分析STL标准模板List的使用及事项
来源:互联网 发布:淘宝 买药 编辑:程序博客网 时间:2024/06/05 09:55
一、List介绍:
List是C++STL标准模板库的重要类模板之一,通俗解释可以看做是双向链表。可在常数时间内在任何位置执行插入和删除操作的顺序容器。
相较于vector的连续线性空间,list就显得复杂许多,它的好处是每次插入或删除一个元素,就配置或释放一个元素空间。因此,list对于空间的运用有绝对的精准,一点也不浪费。而且,对于任何位置的元素插入或元素移除,list永远是常数时间。
list不仅是一个双向链表,而且还是一个环状双向链表。另外,还有一个重要性质,插入操作和接合操作都不会造成原有的list迭代器失效,这在vector是不成立的。因为vector的插入操作可能造成记忆体重新配置,导致原有的迭代器全部失效。甚至list的元素删除操作(erase),也只有“指向被删除元素”的那个迭代器失效,其他迭代器不受任何影响。
二、List分析:
(1)、List内部成员。
相当于一个链表的节点,可用或添加数据类型。
1. struct __list_node
2. {
3. typedef void* void_pointer;
4. void_pointer next;
5. void_pointer prev;
6. T data;
7. };
数据类型可以是int,char,float,string等,具体视需求而定。
还有重要的内部成员类型是迭代器类型。
template<class T, class Ref, class Ptr>
struct __list_iterator
{
typedef __list_iterator<T, T&, T*> iterator; // STL标准强制要求
typedef __list_iterator<T, Ref, Ptr> self;
typedef bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef __list_node<T>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
link_type node; //迭代器内部有一个普通指针,指向list的节点
}
通过重载迭代器的前缀、后缀自加自减,赋值符号等,实现迭代器的移动,即可在链表上进行移动的操作。通过迭代器在链表上的移动找寻相应的位置或元素,进行list的操作。
对于list的存储空间分配,内部有专属的空间配置器,每次配一个节点,其操作类似链表:
// 专属之空间配置器,每次配置一个节点大小
typedef simple_alloc<list_node, Alloc> list_node_allocator;
(2)、接口:
从其功能函数分析其接口,以及完成的功能及返回值。
类型1:与list的容量相关的函数
1、empty
原型:bool empty ( ) const;
功能:判断lsit是否为空,即size是否为0
返回值:size为0,返回true,否则,返回false
2、size
原型:size_type size() const;
功能:返回lsit中元素的个数
返回值:size_type
3、Max_size
原型:size_type max_size () const;
功能:返回lsit的最大容量
返回值:
4、resize
原型:void resize ( size_type sz, T c = T());
功能:重新分配lsit的大小。如果sz小于目前的size就将多余的值删除;如果sz大于目前的size,就在增加容量,且用c填充。例如:
mylist.resize(5); //将size定为5
mylist.resize(8,100); //将size定为8,多出的用100填充
mylist.resize(12); //将size定为12
类型2:获取元素函数:
1、front
原型: reference front ( );
const_reference front ( ) const;
功能:获取第一个元素
返回值:第一个元素的值
2、back
原型:reference back ( );
const_reference back ( ) const
功能:获取最后一个元素
返回值:最后一个元素
类型3:修改lsit的函数
1、assign
原型:void assign ( InputIterator first, InputIterator last );
void assign ( size_type n, const T& u)
功能:为list重新分配空间并赋值。将[first,last)范围内的值或者n次u值的拷贝赋给list
返回值:无
2、push_front:从头插入一个元素。pop_front:删除第一个元素
push_back:在尾部插入一个元素。 pop_back:删除最后一个元素
3、insert
原型:iterator insert ( iterator position, const T& x );
void insert ( iterator position, size_type n, const T& x );
template <class InputIterator>
void insert ( iterator position, InputIterator first, InputIterator last );
功能:插入元素
insert ( iterator position, const T& x ) :在position位置处插入元素x
insert ( iterator position, size_type n, const T& x ):在position位置处开始插入n个x
insert ( iterator position, InputIterator first, InputIterator last ):在position位置处开始插入
[first,last)范围内的元素。
返回值:只有第一个函数返回插入的元素所在位置
4、erase
原型:iterator erase ( iterator position );
iterator erase ( iterator first, iterator last );
功能:清除链表中position 处或者[first,last)范围内的元素。会减少list的size值。
返回值:清除的最后一个元素的下一个位置(迭代器)
5、swap
原型:void swap ( list<T,Allocator>& lst)
功能:将两个lsit交换
6、clear
功能:清空list
类型4:操作类的函数
1、splice
原型:设list2调用了splice函数
void splice ( iterator position, list<T,Allocator>& x );将list x中的所有元素插入到调用该函数的list2的position处。List x会被清空。
void splice ( iterator position, list<T,Allocator>& x, iterator i );将x中指向i的位置处的元素插入到list2的position处。X会将i位置处的值删除。
void splice ( iterator position, list<T,Allocator>& x, iterator first, iterator last ); 将x中[first,last)位置处的元素插入到list2的position处。
功能:Move elements from list to list。将一个lsit中的值移动到另一个list
2、remove
原型:void remove ( const T& value );
功能:清除链表中特定的值value,lsit的size会相应减少。
返回值:无
3、remove_if
原型:template <class Predicate>
void remove_if ( Predicate pred );
功能:在满足Predicate pred返回true值时,移除元素。pred可以是一个返回bool类型的函数,还可以是一个重写operator函数的类。 例如:
// a predicate implemented as a function:
bool single_digit (const int& value) { return (value<10); }
// a predicate implemented as a class:
class is_odd
{
public:
bool operator() (const int& value) {return (value%2)==1; }
};
返回值:无
4、unique
原型:void unique ( );
template <class BinaryPredicate>
void unique ( BinaryPredicate binary_pred );按照规则binary_pred消除重复值。例如:
bool same_integral_part (double first, double second)
{ return ( int(first)==int(second) ); }
// a binary predicate implemented as a class:
class is_near
{
public:
bool operator() (double first, double second)
{ return (fabs(first-second)<5.0); }
};
调用:mylist.unique (same_integral_part);
mylist.unique (is_near());
功能:消除list中的重复元素
返回值:
5、merge
原型:void merge ( list<T,Allocator>& x );
template <class Compare>
void merge ( list<T,Allocator>& x, Compare comp );
功能:合并两个已经有序(同时为升序或降序)的list。
merge()组合起两个排好序的表。如果一个表未排序,merge()仍然能产生出一个表,其中包含着原来两个表元素的并集。当然,对结果的排序就没有任何保证了。向splice()函数一样,merge()函数也不复制元素。
merge函数的作用是:将两个有序的序列合并为一个有序的序列。函数参数:merge(first1,last1,first2,last2,result,compare);//firs1t为第一个容器的首迭代器,last1为第一个容器的末迭代器,first2为第二个容器的首迭代器,last2为容器的末迭代器,result为存放结果的容器,comapre为比较函数(可略写,默认为合并为一个升序序列)。
返回值:
三、内存管理方法:
根据双向链表的特性,只需要一个指针即可表示整个环形双向链表。对于空链表的建立,配置一个节点空间,令node指向它,同时另node头尾都指向自己。同时创建值为value的n个节点只需进行插入操作,时间复杂度为O(1)。
特别要注意的是内存的释放,函数如下:
1. ~list()
2. {
3. // 释放所有结点 // 使用全局函数distance()进行计算, 时间复杂度O(n)
4. size_type size() const
5. {
6. size_type result = 0;
7. distance(begin(), end(), result);
8. return result;
9. }
10. clear();
11. // 释放头结点
12. put_node(node);
13. }
1. // 销毁所有结点, 将链表置空
2. template <class T, class Alloc>
3. void list<T, Alloc>::clear()
4. {
5. link_type cur = (link_type) node->next;
6. while (cur != node)
7. {
8. link_type tmp = cur;
9. cur = (link_type) cur->next;
10. destroy_node(tmp);
11. }
12. // 恢复node原始状态
13. node->next = node;
14. node->prev = node;
15. }
四、封装技巧:
与众多的类模板相同的,使用类的构建,只需要了解函数的内部接口,不关心内部操作的实现。通过代码分析可看出,在list内部有许多的protected类型的数据,如上面所讲述的空间配置器。乃至一些protected类型的函数,这都是为了防止外部的直接访问给内部数据造成的修改。类似下面所举的数据与函数。
1. protected:
2. link_type node ; // 只要一个指针,便可表示整个环状双向链表
3. // 分配一个新结点, 注意这里并不进行构造,
4. // 构造交给全局的construct, 见<stl_stl_uninitialized.h>
5. link_type get_node() { return list_node_allocator::allocate(); }
6.
7. // 释放指定结点, 不进行析构, 析构交给全局的destroy
8. void put_node(link_type p) { list_node_allocator::deallocate(p); }
9.
10. // 产生(配置并构造)一个节点, 首先分配内存, 然后进行构造
11. // 注: commit or rollback
12. link_type create_node(const T& x)
13. {
14. link_type p = get_node();
15. construct(&p->data, x);
16. return p;
17. }
18.
19. // 析构结点元素, 并释放内存
20. void destroy_node(link_type p)
21. {
22. destroy(&p->data);
23. put_node(p);
24. }
五、应用中需要注意的问题与不足:
如在调用erase方法之后使用“++”来获取下一个元素的位置,由于在调用erase方法以后,该元素的位置已经被删除,如果在根据这个旧的位置来获取下一个位置,则会出现异常。
错误样例:
std::list< int> List;
std::list< int>::iterator itList;
for( itList = List.begin(); itList != List.end(); )
{
if( WillDelete( *itList) )
{
itList = List.erase( ++itList);
}
else
itList++;
}
正确使用:
std::list< int> List;
std::list< int>::iterator itList;
for( itList = List.begin(); itList != List.end(); )
{
if( WillDelete( *itList) )
{
List.erase( itList++);
}
else
itList++;
}
同时,调用需要注意几个问题。
1、静态对象必须在类外初始化。
2、因有在类外初始化的需求,静态对象必须是公有的。
linklist<int> list2;
class A
{
public:
static linklist<int> list;
void mod()
{
list.add(10);
}
void print()
{
list.print();
}
};
linklist<int> A::list=list2;
int main()
{
A a;
a.mod();
a.print();
system("pause");
}
附录:
一、List类模板代码及其解析
template <class T>
struct __list_node
{
typedef void* void_pointer;
void_pointer next;
void_pointer prev;
T data;
};
// 不使用默认参数因为有一些编译器不能提供推导能力,
template<class T, class Ref, class Ptr>
struct __list_iterator
{
typedef __list_iterator<T, T&, T*> iterator; // STL标准强制要求
typedef __list_iterator<T, Ref, Ptr> self;
typedef bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef __list_node<T>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
link_type node; //迭代器内部当然要有一个普通指针,指向list的节点
__list_iterator(link_type x) : node(x) {}
__list_iterator() {}
__list_iterator(const iterator& x) : node(x.node) {}
// 在STL算法中需要迭代器提供支持
bool operator==(const self& x) const { return node == x.node; }
bool operator!=(const self& x) const { return node != x.node; }
// 以下对迭代器取值(dereference),取的是节点的数据值
reference operator*() const { return (*node).data; }
// 以下是迭代器的成员存取运算子的标准做法
pointer operator->() const { return &(operator*()); }
// 前缀自加,对迭代器累加1,就是前进一个节点
self& operator++()
{
node = (link_type)((*node).next);
return *this;
}
// 后缀自加, 需要先产生自身的一个副本, 然会再对自身操作, 最后返回副本
self operator++(int)
{
self tmp = *this;
++*this;
return tmp;
}
// 前缀自减
self& operator--()
{
node = (link_type)((*node).prev);
return *this;
}
self operator--(int)
{
self tmp = *this;
--*this;
return tmp;
}
};
////////////////////////////////////////////////////////////////////////////////
// list不仅是个双向链表, 而且还是一个环状双向链表
////////////////////////////////////////////////////////////////////////////////
// end() 头结点 begin()
// ↓ ↓ ↓
// -------- -------- -------- --------
// ---->| next |---------->| next |---------->| next |---------->| next |------
// | -------- -------- -------- -------- |
// | --| prev |<----------| prev |<----------| prev |<----------| prev |<--| |
// | | -------- -------- -------- -------- | |
// | | | data | | data | | data | | data | | |
// | | -------- -------- -------- -------- | |
// | | | |
// | | -------- -------- -------- -------- | |
// ---|-| next |<----------| next |<----------| next |<----------| next |<--|--
// | -------- -------- -------- -------- |
// ->| prev |---------->| prev |---------->| prev |---------->| prev |----
// -------- -------- -------- --------
// | data | | data | | data | | data |
// -------- -------- -------- --------
////////////////////////////////////////////////////////////////////////////////
// 默认allocator为alloc, 其具体使用版本请参照<stl_alloc.h>
template <class T, class Alloc = alloc>
class list
{
protected:
typedef void* void_pointer;
typedef __list_node<T> list_node;
// 专属之空间配置器,每次配置一个节点大小
typedef simple_alloc<list_node, Alloc> list_node_allocator;
public:
typedef T value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef list_node* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef __list_iterator<T, T&, T*> iterator;
protected:
link_type node ; // 只要一个指针,便可表示整个环状双向链表
// 分配一个新结点, 注意这里并不进行构造,
// 构造交给全局的construct, 见<stl_stl_uninitialized.h>
link_type get_node() { return list_node_allocator::allocate(); }
// 释放指定结点, 不进行析构, 析构交给全局的destroy
void put_node(link_type p) { list_node_allocator::deallocate(p); }
// 产生(配置并构造)一个节点, 首先分配内存, 然后进行构造
// 注: commit or rollback
link_type create_node(const T& x)
{
link_type p = get_node();
construct(&p->data, x);
return p;
}
// 析构结点元素, 并释放内存
void destroy_node(link_type p)
{
destroy(&p->data);
put_node(p);
}
protected:
// 用于空链表的建立
void empty_initialize()
{
node = get_node(); // 配置一个节点空间,令node指向它
node->next = node; // 令node头尾都指向自己,不设元素值
node->prev = node;
}
// 创建值为value共n个结点的链表
// 注: commit or rollback
void fill_initialize(size_type n, const T& value)
{
empty_initialize();
__STL_TRY
{
// 此处插入操作时间复杂度O(1)
insert(begin(), n, value);
}
__STL_UNWIND(clear(); put_node(node));
}
public:
list() { empty_initialize(); }
iterator begin() { return (link_type)((*node).next); }
// 链表成环, 当指所以头节点也就是end
iterator end() { return node; }
// 头结点指向自身说明链表中无元素
bool empty() const { return node->next == node; }
// 使用全局函数distance()进行计算, 时间复杂度O(n)
size_type size() const
{
size_type result = 0;
distance(begin(), end(), result);
return result;
}
size_type max_size() const { return size_type(-1); }
reference front() { return *begin(); }
reference back() { return *(--end()); }
////////////////////////////////////////////////////////////////////////////////
// 在指定位置插入元素
////////////////////////////////////////////////////////////////////////////////
// insert(iterator position, const T& x)
// ↓
// create_node(x)
// p = get_node();-------->list_node_allocator::allocate();
// construct(&p->data, x);
// ↓
// tmp->next = position.node;
// tmp->prev = position.node->prev;
// (link_type(position.node->prev))->next = tmp;
// position.node->prev = tmp;
////////////////////////////////////////////////////////////////////////////////
iterator insert(iterator position, const T& x)
{
link_type tmp = create_node(x); // 产生一个节点
// 调整双向指针,使tmp插入进去
tmp->next = position.node;
tmp->prev = position.node->prev;
(link_type(position.node->prev))->next = tmp;
position.node->prev = tmp;
return tmp;
}
// 指定位置插入n个值为x的元素, 详细解析见实现部分
void insert(iterator pos, size_type n, const T& x);
void insert(iterator pos, int n, const T& x)
{
insert(pos, (size_type)n, x);
}
void insert(iterator pos, long n, const T& x)
{
insert(pos, (size_type)n, x);
}
// 在链表前端插入结点
void push_front(const T& x) { insert(begin(), x); }
// 在链表最后插入结点
void push_back(const T& x) { insert(end(), x); }
// 移除迭代器position所指节点
iterator erase(iterator position)
{
link_type next_node = link_type(position.node->next);
link_type prev_node = link_type(position.node->prev);
prev_node->next = next_node;
next_node->prev = prev_node;
destroy_node(position.node);
return iterator(next_node);
}
// 擦除一个区间的结点, 详细解析见实现部分
iterator erase(iterator first, iterator last);
void resize(size_type new_size, const T& x);
void resize(size_type new_size) { resize(new_size, T()); }
void clear();
// 删除链表第一个结点
void pop_front() { erase(begin()); }
// 删除链表最后一个结点
void pop_back()
{
iterator tmp = end();
erase(--tmp);
}
list(size_type n, const T& value) { fill_initialize(n, value); }
list(int n, const T& value) { fill_initialize(n, value); }
list(long n, const T& value) { fill_initialize(n, value); }
~list()
{
// 释放所有结点 // 使用全局函数distance()进行计算, 时间复杂度O(n)
size_type size() const
{
size_type result = 0;
distance(begin(), end(), result);
return result;
}
clear();
// 释放头结点
put_node(node);
}
list<T, Alloc>& operator=(const list<T, Alloc>& x);
protected:
////////////////////////////////////////////////////////////////////////////////
// 将[first, last)内的所有元素移动到position之前
// 如果last == position, 则相当于链表不变化, 不进行操作
////////////////////////////////////////////////////////////////////////////////
// 初始状态
// first last
// ↓ ↓
// -------- -------- -------- -------- -------- --------
// | next |-->| next |-->| next | | next |-->| next |-->| next |
// ... -------- -------- -------- ... -------- -------- -------- ...
// | prev |<--| prev |<--| prev | | prev |<--| prev |<--| prev |
// -------- -------- -------- -------- -------- --------
//
// position
// ↓
// -------- -------- -------- -------- -------- --------
// | next |-->| next |-->| next |-->| next |-->| next |-->| next |
// ... -------- -------- -------- -------- -------- -------- ...
// | prev |<--| prev |<--| prev |<--| prev |<--| prev |<--| prev |
// -------- -------- -------- -------- -------- --------
//
// 操作完成后状态
// first
// |
// --------------|--------------------------------------
// | ------------|------------------------------------ | last
// | | ↓ | | ↓
// -------- | | -------- -------- -------- | | -------- --------
// | next |-- | ----->| next |-->| next | | next |----- | -->| next |-->| next |
// ... -------- | | -------- -------- ... -------- | | -------- -------- ...
// | prev |<--- | ---| prev |<--| prev | | prev |<-- | -----| prev |<--| prev |
// -------- | | -------- -------- -------- | | -------- --------
// | | | |
// | ------ | |
// ------- | ------------------------------ |
// | | | |
// | | | -----------------------------
// | | | |
// | | | | position
// | | | | ↓
// -------- -------- | | | | -------- -------- -------- --------
// | next |-->| next |-- | | -->| next |-->| next |-->| next |-->| next |
// ... -------- -------- | | -------- -------- -------- -------- ...
// | prev |<--| prev |<--- ------| prev |<--| prev |<--| prev |<--| prev |
// -------- -------- -------- -------- -------- --------
////////////////////////////////////////////////////////////////////////////////
void transfer(iterator position, iterator first, iterator last)
{
if (position != last) // 如果last == position, 则相当于链表不变化, 不进行操作
{
(*(link_type((*last.node).prev))).next = position.node;
(*(link_type((*first.node).prev))).next = last.node;
(*(link_type((*position.node).prev))).next = first.node;
link_type tmp = link_type((*position.node).prev);
(*position.node).prev = (*last.node).prev;
(*last.node).prev = (*first.node).prev;
(*first.node).prev = tmp;
}
}
public:
// 将链表x移动到position所指位置之前
void splice(iterator position, list& x)
{
if (!x.empty())
transfer(position, x.begin(), x.end());
}
// 将链表中i指向的内容移动到position之前
void splice(iterator position, list&, iterator i)
{
iterator j = i;
++j;
if (position == i || position == j) return;
transfer(position, i, j);
}
// 将[first, last}元素移动到position之前
void splice(iterator position, list&, iterator first, iterator last)
{
if (first != last)
transfer(position, first, last);
}
void remove(const T& value);
void unique();
void merge(list& x);
void reverse();
void sort();
};
// 销毁所有结点, 将链表置空
template <class T, class Alloc>
void list<T, Alloc>::clear()
{
link_type cur = (link_type) node->next;
while (cur != node)
{
link_type tmp = cur;
cur = (link_type) cur->next;
destroy_node(tmp);
}
// 恢复node原始状态
node->next = node;
node->prev = node;
}
// 链表赋值操作
// 如果当前容器元素少于x容器, 则析构多余元素,
// 否则将调用insert插入x中剩余的元素
template <class T, class Alloc>
list<T, Alloc>& list<T, Alloc>::operator=(const list<T, Alloc>& x)
{
if (this != &x)
{
iterator first1 = begin();
iterator last1 = end();
const_iterator first2 = x.begin();
const_iterator last2 = x.end();
while (first1 != last1 && first2 != last2) *first1++ = *first2++;
if (first2 == last2)
erase(first1, last1);
else
insert(last1, first2, last2);
}
return *this;
}
// 移除容器内所有的相邻的重复结点
// 时间复杂度O(n)
// 用户自定义数据类型需要提供operator ==()重载
template <class T, class Alloc>
void list<T, Alloc>::unique()
{
iterator first = begin();
iterator last = end();
if (first == last) return;
iterator next = first;
while (++next != last)
{
if (*first == *next)
erase(next);
else
first = next;
next = first;
}
}
// 假设当前容器和x都已序, 保证两容器合并后仍然有序
template <class T, class Alloc>
void list<T, Alloc>::merge(list<T, Alloc>& x)
{
iterator first1 = begin();
iterator last1 = end();
iterator first2 = x.begin();
iterator last2 = x.end();
// 注意:前提是,两个lists都已经递增排序
while (first1 != last1 && first2 != last2)
if (*first2 < *first1)
{
iterator next = first2;
transfer(first1, first2, ++next);
first2 = next;
}
else
++first1;
if (first2 != last2)
transfer(last1, first2, last2);
}
二、List使用样例程序:
/*
熟悉链表的库函数操作:创建链表,插入元素,删除元素,查找元素,为链表排序 遍历元素 掌握其使用
*/
#include <iostream>
#include <list> //链表头文件
#include <algorithm> //find函数头文件
using namespace std;
int main()
{
list<int> L;
list<int>::iterator it;
//插入元素 输出
int i=0,n; //插入数量
int num;
cout<<"输入要插入元素的个数:";
cin>>n;
cout<<"输入"<<n<<"个元素:"<<endl;
while (i<n)
{
cin>>num;
L.push_back(num); //重尾部插入元素 这样可以保证元素的顺序正确
i++;
}
//输出
for (it=L.begin(); it!=L.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
//查找元素
int searh;
cout<<"输入要找的元素:";
cin>>searh;
it = find(L.begin(), L.end(), searh);
if (it!=L.end())
{
cout<<searh<<"查找成功"<<endl;
}
else
{
cout<<"查找失败"<<endl;
}
//排序
L.sort();
//输出
cout<<"排好序后的元素为:"<<endl;
for (it=L.begin(); it!=L.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
//删除元素
int k = 0;
int de;
cout<<"输入要删除第几个元素:";
cin>>de;
while (k!=de)
{
it++;
k++;
}
L.erase(it); //删除元素 remove函数也行,相同元素一起删除
cout<<"删除后的元素为:"<<endl;
for (it=L.begin(); it!=L.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
//插入元素
int inser,m,h=0;
cout<<"输入要插入的元素:";
cin>>inser;
cout<<"输入要插入的位置:";
cin>>m;
while (h!=m)
{
it++;
h++;
}
//插入元素
L.insert(it, inser); //在it位置插入num
cout<<"插入后的元素为:"<<endl;
for (it=L.begin(); it!=L.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
return 0;
}
- 深入分析STL标准模板List的使用及事项
- STL标准模板库 list的使用
- STL标准模板类库-LIST的使用
- C++的标准模板库STL中实现的数据结构之链表std::list的分析与使用
- 标准模板库使用举例(STL - (LIST,VECTOR))
- 标准模板库STL中List使用参考手册
- STL]标准模板库(STL)List
- STL 标准模板库 vector queue list map multimap的使用基础
- (Zz)STL 简介,标准模板库(list)
- STL 简介,标准模板库 list
- 标准模板库STL之list
- 标准STL中list的各个接口的使用
- STL 标准模板库 中栈stack 容器的使用
- C++的标准模板库STL中实现的数据结构之顺序表vector的分析与使用
- 使用C++ STL需要注意的事项
- C++ STL和标准模板库及C标准库的关系
- STL模板库中Vector与List的使用
- 使用标准模板库 (STL)之一
- 5 insanely great books about mathematics you should read.
- C/C++学习笔记33:面试题中常见的位操作问题
- Microsoft100——006.判断树B是不是树A的子结构
- hdu4982 暴搜+剪枝(k个数和是n,k-1个数的和是平方数)
- 【线性代数】方程组的几何解释
- 深入分析STL标准模板List的使用及事项
- 数据结构-【链表】单向链表的逆置和双向循环链表
- javascript原生移动云编程3 - 比web还简单的页面UI布局
- Unity 编译顺序及原理
- UVA10714
- Shell常识--校验和、核实以及加密--总结自《Linux Shell 脚本攻略》
- Spiral Matrix
- [Android View] QuickReturn (自动隐藏header/footer view)
- poj 2726 Holiday Hotel (排序&&单调栈)