- list不能使用STL算法的sort() ——快排,必须使用自己的成员函数sort() 。
- 因为STL算法sort()只接受RandomAccessIterator。
- list排序采用了mergesort,时间复杂度是O(nlgn),空间复杂度是O(1)。
template<class T>
struct _list_node{
typedef void * void_pointer;
void_pointer prev;
void_pointer next;
T data;
};
template<class T>
class
{
protected:
_list_node<T> * node;//用一个指针,表示整个环状双向链表
protected:
//将[first,last)内的所有元素移动到position之前。
void transfer(iterator position,iterator first,iterator last){
... ...
}
public:
void sort();
void merge(list<T> & x);
};
template<class T>
void list<T>::merge(list<T> & x)
{
iterator first1 = begin();
iterator last1 = end();
iterator first2 = x.begin();
iterator last2 = x.end();
while(first1 != last1 && first2 != last2 )
{
if(*first2<*first1){
iterator next = first2;
transfer(first1,first2,++next);//将[first2,next)的元素移动到first1之前。
first2 = next;
}
else
++first1;
}
if(first2 != last2) transfer(last1,first2,last2);
}
template<class T>
void list<T>::sort()
{
//当链表为空或者仅有一个元素,就不进行任何操作
if(node->next==node || node->next->next ==node)
return ;
list<T> carry;
list<T> counter[64];//用来保存一系列的合并后的有序链表,每一层保存的最大结点数目1,2,4,...
int fill=0; //记录了counter数组现在最多使用了几层
while(!empty() ){ //当链表不为空
carry.splice(carry.begin(),*this,begin());//将链表的头一个结点截取到carry上。
int i=0; //i,表示counter的下标
while(i<fill && !counter[i].empty() ){
counter[i].merge(carry); //将carry合并到counter[i]链表上,carry为空
carry.swap(counter[i++]); //交换carry和counter[i],以便和i+1层的合并
}
carry.swap(counter[i]);
if(i==fill) ++fill;
}
for(int i=1;i<fill;++i) //将所有保存在counter中的有序链表合并到一起
counter[i].merge(counter[i-1]);
swap(counter[fill-1]; //将在counter[fill-1]排序好的链表交换给this链表。
}
举例:现有链表其值为{5,9,3,11,1,20},调用list的sort函数;
while(!empty()) 的第一次循环后:
this链表 | {9,3,11,1,20} |
carry | {5} ---> empty |
counter[0] | {5} |
counter[1] | empty |
fill | 1 |
while(!empty()) 的第二次循环后:
this链表 | {3,11,1,20} |
carry | {9} ---> {5,9} --->empty |
counter[0] | empty |
counter[1] | {5,9} |
counter[2] | empty |
fill | 2 |
while(!empty()) 的第三次循环后:
this链表 | {11,1,20} |
carry | {3} --->empty |
counter[0] | {3} |
counter[1] | {5,9} |
counter[2] | empty |
fill | 2 |
while(!empty()) 的第四次循环后:
this链表 | {1,20} |
carry 变化过程 | {11} ---> {3,11}--->{3,5,9,11}--->empty |
counter[0] | empty |
counter[1] | empty |
counter[2] | {3,5,9,11} |
fill | 3 |
while(!empty()) 的第五次循环后:
this链表 | {20} |
carry | {1} ---> empty |
counter[0] | {1} |
counter[1] | empty |
counter[2] | {3,5,9,11} |
fill | 3 |
while(!empty()) 的第六次循环后:
this链表 | empty |
carry | {20} ---> {1,20} ---> empty |
counter[0] | empty |
counter[1] | {1,20} |
counter[2] | {3,5,9,11} |
fill | 3 |
最后将前0层到fill-1层, counter合并到counter[fill-1].然后交换给this链表。
counter[2] | {1,3,5,9,11,20} ---> empty |
this链表 | {1,3,5,9,11,20} |