目录
目录
unique:唯一化链表中的节点,将连续相同的元素移除至只剩一个,不连续的相同元素不会被移除
splice:拼接,将某连续范围内的元素从一个list移动到另一个(或同一个)list的某个position
merge:有序合并,将升序排列的list1合并到升序排列的list2上,前提时list1和list2都必须升序有序,合并后的list也是升序
reverse:反转list, 如1->2->3->4反转后为4->3->2->1
sort:排序,list不能使用STL提供的sort算法,只能使用自己的sort()成员函数,因为STL中的sort只接受支持随机访问的iterator,而list当中的迭代器无法随机访问;
list概述:
list的好处是每次插入或删除一个元素,只需配置或释放一个元素空间,所以list对于任意位置元素的插入或删除都是常数时间
list节点的结构(单个list节点的结构)
template <Class T>
struct _list_node {
typedef void* void_pointer;
void_pointer prev;
void_pointer next;
T data;
}
list的数据结构(表示整个list的结构)
templat <class T, class Alloc = alloc>
class list{
protected:
typedef _list_node<T> list_node;
public:
typedef list_node* link_type;
protected:
link_type node; //只要一个指针,便可表示整个环状双向链表
...
}
显然,list是双向链表,并且是双向循环链表,只需刻意在尾端添加一个空白节点,指针node便可满足“前闭后开”的区间要求
list的迭代器
list的一个重要性质:insert和splice操作都不会导致原有list迭代器失效,erase操作也只是导致之前指向待删除节点的迭代器失效,其他迭代器不受影响。因为list插入和接合操作只需改变节点pre和next的指向,不会改变当前节点所处的内存位置;
list迭代器的设计:
template <class T, class Ref, class Ptr>
struct _list_iterator {
//类型重命名
typedef _list_iterator<T, T&, T*> iterator;
typedef _list_iterator<T, Ref, Ptr> self;
typedef bidirectional_iterator_tag itreator_category;
typedef T value_type;
typedef Ref pointer;
typedef Ptr reference;
typedef _list_node<T>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
//迭代器中的成员
link_type node; //指向list节点的指针;
//迭代器的构造函数
_list_iterator() {} //默认构造
_list_iterator(link_type x) : node(x) {} //参数类型为link_type的构造
_list_iterator(const iterator& x) : node(x.node) {} //参数类型为某list的迭代器
//迭代器必备的重载函数
bool operator==(const self& x) const {return node== x.node};
bool operator!=(const self& x) const {renturn node!= x.node};
reference operator*() const {return (*node).data;}
pointer operator->() const {return &( operator*() );}
//对迭代器累加1,即前进一个节点
self& operator++() {
node = (link_type) ((*node).next);
return *this; //this代表指向当前对象的指针 return this 即为 返回当前对象的地址
//*this代表当前对象的拷贝或者本身, 若返回类型为A 则是返回拷贝, 若返回类型是A& 则是返回本身
}
//累加的重载版本,没看懂
self operator++(int) {
self tmp = *this; //tmp是iterator,*this是对象的拷贝
++*this; //什么意思?
return tmp;}
//对迭代器递减,即后退一个节点
self& operator--() {
node = (link_type) ((*node).next);
return *this;}
self operator--(int) {
self tmp = *this; //tmp是iterator,*this是对象的拷贝
--*this; //什么意思?
return tmp;}
}
如何判断list为空?
begin()->prev==bengin()&&begin()->next==begin()
即list节点node的prev和next都指向自身
list的内存管理
constructor、push_back、insert;
insert函数:
iterator insert(iterator position, const T& x)//在position位置插入 x
当使用push_back()函数尾插新元素时,内部调用的就是insert(),其中position的位置可以通过find()来确定
find函数:
iterator find (begin,end,const T& x);//在begin至end范围内,查找value=x的节点,并返回其迭代器
注意:list中在position位置插入是指将某节点插入到position位置的前一个位置上;
list的元素操作
常用操作有:
push_front、push_back、pop_front、pop_back
erase:移除迭代器所指节点
iterator erase(iterator position){...}
clear:清除整个list的所有节点
void clear() {...}
remove:将数值为value的节点全部移除
void remove(const T& value){...}
unique:唯一化链表中的节点,将连续相同的元素移除至只剩一个,不连续的相同元素不会被移除
void unique(){...}
splice:拼接,将某连续范围内的元素从一个list移动到另一个(或同一个)list的某个position
//1.将整个list1拼接到list2的position位置
void splice (iterator position, list1&,) {...}
//2.将list1中iterator i所指的节点拼接到list2的position位置
void splice (iterator position, list1&, iterator i) {...}
//3.将list1中某一连续范围[first,last)内的节点拼接到list2的position位置
void splice (iterator position, list1&, iterator first, iterator last)
merge:有序合并,将升序排列的list1合并到升序排列的list2上,前提时list1和list2都必须升序有序,合并后的list也是升序
void merge (list& list1){...}
transfer:为list内部提供的一个所谓的迁移操作,将某连续范围内元素迁移到某特定位置之前,主要是做一些节点指针移动的操作,splice和merge两个涉及迁移的函数内部都是transfer函数,但transfer不提供对外接口;程序员无法直接调用;
reverse:反转list, 如1->2->3->4反转后为4->3->2->1
void reverse() {...} //内部使用while循环,搭配快慢指针,将节点依次反转;
sort:排序,list不能使用STL提供的sort算法,只能使用自己的sort()成员函数,因为STL中的sort只接受支持随机访问的iterator,而list当中的迭代器无法随机访问;
void list<T>::sort() {...}//内部实现细节暂略