list::sort源码剖析

来源:互联网 发布:js获取焦点input边框 编辑:程序博客网 时间:2024/05/17 18:42

一:用法示例

函数原型:

有两个重载。

(1)void sort();

(2)template <class Compare>
              void sort (Compare comp);

实现功能:对链表进行排序,默认是升序,如自定义是降序,需使用重载类型第二个,具体操作看下面的示例。


示例:

// list::sort#include <iostream>#include <list>#include <string>#include <cctype>// comparison, not case sensitive.bool compare_nocase(const std::string& first, const std::string& second){unsigned int i = 0;while ((i < first.length()) && (i < second.length())){if (tolower(first[i]) < tolower(second[i])) return true;else if (tolower(first[i]) > tolower(second[i])) return false;++i;}return (first.length() < second.length());}int main(){std::list<std::string> mylist;std::list<std::string>::iterator it;mylist.push_back("one");mylist.push_back("two");mylist.push_back("Three");mylist.sort();std::cout << "mylist contains:";for (it = mylist.begin(); it != mylist.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';mylist.sort(compare_nocase);std::cout << "mylist contains:";for (it = mylist.begin(); it != mylist.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;}

Output:

mylist contains: Three one twomylist contains: one Three two


二:源码

template <class _Tp, class _Alloc>void list<_Tp, _Alloc>::sort(){if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node){list<_Tp, _Alloc> __carry;list<_Tp, _Alloc> __counter[64];int __fill = 0;while (!empty()){__carry.splice(__carry.begin(), *this, begin());int __i = 0;while (__i < __fill && !__counter[__i].empty()){__counter[__i].merge(__carry); __carry.swap(__counter[__i++]);}__carry.swap(__counter[__i]);        if (__i == __fill) ++__fill;}for (int __i = 1; __i < __fill; ++__i)__counter[__i].merge(__counter[__i - 1]);swap(__counter[__fill - 1]);}}


三:源码剖析

template <class _Tp, class _Alloc>void list<_Tp, _Alloc>::sort(){//链表长度如果是0或者1,直接结束。这里没有使用size()是因为速度相对源码的这样设计会慢。if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node){list<_Tp, _Alloc> __carry;list<_Tp, _Alloc> __counter[64];int __fill = 0;/*定义了一个类似于搬运作用的链表carry和具有中转站作用的链表counter,这里首先对counter[i]里面存储数据的规则进行分析;counter[i]里面最多存储数据个数为2^(i+1),若存储数据超过该数字,则向相邻高位进位,即把counter[i]链表里的内容都合并到counter[i+1]链表。carry负责取出原始链表的头一个数据节点和交换数据中转站作用;源码中的fill表示当前可处理数据的个数为2^fill.那么counter数组长度64,也就是排序元素个数最多可到2^64-1,这数据量已经足够。*/while (!empty()){__carry.splice(__carry.begin(), *this, begin());//把当前链表的第一个节点放在carry链表头int __i = 0;while (__i < __fill && !__counter[__i].empty()){__counter[__i].merge(__carry);//把链表carry合并到counter[i]__carry.swap(__counter[__i++]);//交换链表carry和counter[i]内容  }__carry.swap(__counter[__i]);//交换链表carry和counter[i]内容if (__i == __fill) ++__fill;}for (int __i = 1; __i < __fill; ++__i)__counter[__i].merge(__counter[__i - 1]);//把低位不满足进位的剩余数据全部有序的合并到上一位swap(__counter[__fill - 1]);//最后把已排序好的链表内容交换到当前链表}}

建议读者在阅读一些算法代码,尤其是经典的源代码时,如果在理解上有困难,一定要自己设计测试数据,然后再纸上模拟算法流程,由此加深理解。




点击进入目录----> C++源码剖析目录







  


 



1 0
原创粉丝点击