STL中的List排序问题

    最近想钻研一下STL源代码,于是照着侯捷的《STL源码剖析》看SGI STL,今天想写写list的排序算法。源代码如下:

 

template <class _Tp, class _Alloc> template <class _StrictWeakOrdering>
void list<_Tp, _Alloc>::sort(_StrictWeakOrdering __comp)
{
  // Do nothing if the list has length 0 or 1.
  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, __comp);
        __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], __comp);
    swap(__counter[__fill-1]);
  }
}

      侯捷说这是快排算法!不可思议,虽然第一眼看上去看不出什么,但第一印象绝对不是快排,多半是合并排序。经过自己的深入研究,现在终于可以打包票了!

      首先,要明白 __counter[64] 的含义。__counter[i] 表示长度为 2^i 的一段有序数据,当然是来自于待排序的list。fill 表示现在最大的有序数据长度——2^fill。

 

      每次 carry 从list中获取一个数据,和 __counter[0] 合并,并把__counter[0] 的内容给carry,且清空__counter[0]。接着carry和__counter[1] 合并,把__counter[1]赋给carry,清空__counter[1], 以此类推,一直到 __counter[i] 为空,或是 i==__fill(此时carry的长度是 2^(__fill+1) )。接着我们可以看到 __fill ++ 。

 

       我想要注意一下__counter[i] 的长度为空时的情况。此时 carry 的有序数据的个数是 2^i ,但是长度是 2^i 的缓冲区__counter 为空,毫无疑问,我们应该用__counter[i] 保存 carry 的有序数据。

 

       最后,当list为空时,数据散落在 __counter[] 中,它们都是有序的,只需要以此合并就可以了。时间复杂度就不用说了。

       感觉思路真的很巧妙,自己有必要实现一个简单的list,且重点实现排序算法,算是练练手吧,好久没敲过代码。

       睡觉!

      转载:http://blog.csdn.net/hpghy123456/article/details/5544500

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值