Chinaunix首页 | 论坛 | 博客
  • 博客访问: 135320
  • 博文数量: 13
  • 博客积分: 431
  • 博客等级: 下士
  • 技术积分: 166
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-18 14:59
文章分类

全部博文(13)

文章存档

2012年(9)

2011年(4)

分类: C/C++

2012-02-26 08:20:44

STL的list容器提供了专有的sort算法,是一个以非递归形式的merge sort,虽然研究多时,无奈本人算法功底不济,本文权当抛砖引玉,望各路高手指点。

代码:
  1. template <class _Tp, class _Alloc>
  2. template <class _StrictWeakOrdering>
  3. void list<_Tp, _Alloc>::sort(_StrictWeakOrdering __comp)
  4. {
  5.     // Do nothing if the list has length 0 or 1.
  6.     if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) {
  7.         // 保存下层merge返回的结果
  8.         list<_Tp, _Alloc> __carry;
  9.         // 模拟merge sort使用的堆栈,保存部分有序的list
  10.         // 64应该写作sizeof(size_type) * 8,即最大的递归调用层次。
  11.         list<_Tp, _Alloc> __counter[64];
  12.         // 指示堆栈层次
  13.         int __fill = 0;
  14.         while (!empty()) {
  15.             // 将begin处的元素从list取下,insert到carry中
  16.             __carry.splice(__carry.begin(), *this, begin());
  17.             int __i = 0;
  18.             // 模拟递归时对下层的返回结果进行merge,并将结果交给carry
  19.             while(__i < __fill && !__counter[__i].empty()) {
  20.                 __counter[__i].merge(__carry, __comp);
  21.                 __carry.swap(__counter[__i++]);
  22.             }
  23.             // carry将结果保存到堆栈
  24.             __carry.swap(__counter[__i]);
  25.             // 更新递归层次
  26.             if (__i == __fill) ++__fill;
  27.         }

  28.         // 逐级获取结果
  29.         for (int __i = 1; __i < __fill; ++__i)
  30.             __counter[__i].merge(__counter[__i-1], __comp);
  31.         // 保存最终结果
  32.         swap(__counter[__fill-1]);
  33.     }
  34. }
再免费赠送一个正常merge sort的C实现:)
  1. void merge(int *vector, size_t size)
  2. {
  3.     // return if there's 0 or 1 element.
  4.     if (size <= 1) {
  5.         return ;
  6.     }

  7.     int half = size / 2;

  8.     merge(vector, half);
  9.     merge(vector + half, size - half);

  10.     merge_aux(vector, size);

  11.     return ;
  12. }

  13. static void merge_aux(int *vector, size_t size)
  14. {
  15.     int i, j, k;

  16.     int half = size / 2;

  17.     int clone[half];

  18.     for (i = 0; i < half; ++i) {
  19.         clone[i] = vector[i];
  20.     }

  21.     for (i = 0, j = half, k = 0; (i < half) && (j < size); ++k) {
  22.         if (clone[i] < vector[j]) {
  23.             vector[k] = clone[i++];
  24.         }
  25.         else {
  26.             vector[k] = vector[j++];
  27.         }
  28.     }

  29.     while (i < half) {
  30.         vector[k++] = clone[i++];
  31.     }

  32.     return ;
  33. }
以下以对数据(5, 4, 3, 2, 1)排序为例,比较二者的主要差别。

1)递归形式:(圆圈内为本层排序好的数据)

图1

因为递归形式的merge sort在每一层都对数据进行分解,所以递归树是一棵完全二叉树。

2)非递归形式:

图2

因为非递归形式的算法是自底向上来merge数据,原始数据都处在同一层上,所以部分数据缺少中间的层次,最后仍然需要对这些结果再做一次合并(图2虚线引出的那些单元,就是由list::sort中最后那个for循环所处理)。

另外,由list本身来提供sort算法并不符合STL的设计原则,但若要将这样一个严重依赖底层实现的算法抽象出来,又需要做哪些改动呢?欢迎大家讨论。
阅读(6730) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~