stl-stable_sort源码学习笔记

本文详细解读了STL算法中的稳定排序过程,从申请排序缓冲区到借助缓冲区进行归并排序,再到整个集合分片地进行插入排序,最终通过合并不同分片(有序的)元素实现稳定排序。深入剖析了关键步骤,如递归、归并排序、插入排序等,并通过代码注释展示其具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分享该算法的内在,主要想说明区别于通用型的std::sort。 
    希望贴出来,对于一些新学者有点用处! 
---
Title:
[stl-stable_sort源码学习笔记]
===== begin =====
 STL算法 (稳定)在位排序
 stable_sort(__first,  __last) {
 // 关键点1:申请排序缓冲区
  _Temporary_buffer<_RandomAccessIter, _Tp> buf(__first, __last);
  if (buf.begin() == 0)
    __inplace_stable_sort(__first, __last);//若缓冲区为空则内部排序。
  else 
    __stable_sort_adaptive(__first, __last, buf.begin(),
                           _Distance(buf.size()));//转调 
}
=====>>>>>
转调的在位排序,实则归并排序。
__stable_sort_adaptive(__first, __last, __buffer,__buffer_size) {
// 关键点2:递归,归并排序!
  __len = (__last - __first + 1) / 2;
  __middle = __first + __len;
  if (__len > __buffer_size) {
    __stable_sort_adaptive(__first, __middle, __buffer, __buffer_size);
    __stable_sort_adaptive(__middle, __last, __buffer, __buffer_size);
  }
  else {
    __merge_sort_with_buffer(__first, __middle, __buffer, (_Distance*)0);
    __merge_sort_with_buffer(__middle, __last, __buffer, (_Distance*)0);
  }
  __merge_adaptive(__first, __middle, __last, _Distance(__middle - __first), 
                   _Distance(__last - __middle), __buffer, __buffer_size);
}
=====>>>>>
借助缓冲区进行归并排序
__merge_sort_with_buffer(__first, __last, __buffer) {
  __len = __last - __first;
  __buffer_last = __buffer + __len;
  __step_size = __stl_chunk_size;// sgi stl 7
  // 关键点3:在整个集合分片地进行插入排序,保证每分片均有序。
  __chunk_insertion_sort(__first, __last, __step_size);
  // 关键点4:合并不同分片(有序的)元素。
  while (__step_size < __len) {
    __merge_sort_loop(__first, __last, __buffer, __step_size);
    __step_size *= 2;
    __merge_sort_loop(__buffer, __buffer_last, __first, __step_size);
    __step_size *= 2;
  }
}
=====>>>>> 
__merge_sort_loop(__first,  __last, __result, __step_size) {
  __two_step = 2 * __step_size;
  while (__last - __first >= __two_step) {
    __result = merge(__first, __first + __step_size,
                     __first + __step_size, __first + __two_step,
                     __result);
    __first += __two_step;
  }

  __step_size = min((__last - __first), __step_size);
  merge(__first, __first + __step_size, __first + __step_size, __last,
        __result);
}
=====>>>>>
将集合切分若干分片,排序每分片元素。
__chunk_insertion_sort(__first, __last, __chunk_size)
{
  while (__last - __first >= __chunk_size) {
    __insertion_sort(__first, __first + __chunk_size);
    __first += __chunk_size;
  }
  __insertion_sort(__first, __last);
}
=====>>>>>
插入排序
__insertion_sort(__first, __last) { 
  for (__i = __first + 1; __i != __last; ++__i)
    __linear_insert(__first, __i, __VALUE_TYPE(__first));
}
=====>>>>>
__linear_insert( __first, __last, _Tp*) {
  if (__val < *__first) {
    copy_backward(__first, __last, __last + 1);
    *__first = __val;
  }
  else
    __unguarded_linear_insert(__last, __val);
}
=====>>>>>
__unguarded_linear_insert(__last, __val) {
  __next = __last;
  --__next;
  while (__val < *__next) {
    *__last = *__next;
    __last = __next;
    --__next;
  }
  *__last = __val;
}
===== end =====
### C++ `std::stable_sort` 源码解析 #### 函数签名 `std::stable_sort` 是 C++ 标准模板库 (STL) 中的一个算法,用于执行稳定排序操作。该函数有两种重载形式: ```cpp template<class RandomIt> void stable_sort(RandomIt first, RandomIt last); template<class RandomIt, class Compare> void stable_sort(RandomIt first, RandomIt last, Compare comp); ``` 这两种版本分别对应于默认比较器和自定义比较器的情况。 #### 排序策略概述 为了保持稳定性并优化性能,`std::stable_sort` 使用了一种混合排序方法,在不同情况下采用不同的底层算法来达到最佳效果。对于较小的数据集,通常会使用插入排序;而对于较大的数据集,则可能结合归并排序或其他高效排序技术[^4]。 #### 关键实现细节 具体到 GCC 的 STL 实现中,`std::stable_sort` 主要通过以下方式工作: 1. **分块处理**:当输入序列较大时,首先将其划分为多个固定大小的小片段(称为“chunks”),并对这些片段单独应用插入排序以提高局部有序度。 2. **临时缓冲区管理**:利用 `_GLIBCXX_CALL_WITH_ALLOCATION_TRAITS` 宏获取足够的连续内存空间作为辅助存储区域,以便后续合并阶段能够顺利进行[^3]。 3. **多路归并过程**:完成初步排序后,程序进入核心部分——即基于二叉树结构的多路归并逻辑。这里涉及到复杂的迭代器运算以及边界条件判断,确保最终输出既满足全局顺序又保留原始相等元素间的相对位置关系。 以下是简化版的核心代码框架展示: ```cpp template<typename _RandomAccessIterator, typename _Compare> inline void __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; const difference_type n = std::distance(__first, __last); if(n < 2){ return ; } // 获取临时缓存 pair<void*, ptrdiff_t> buffer_info = get_temporary_buffer(value_type)(__last - __first); value_type* temp_buf = static_cast<value_type*>(buffer_info.first); try { // 对小规模数组直接调用 insertion sort chunk_insertion_sort(__first, __last, S_chunk_size); // 执行 merge pass... // 清理资源 return_temporary_buffer(temp_buf, buffer_info.second); } catch (...) { return_temporary_buffer(temp_buf, buffer_info.second); throw; } } ``` 此段伪代码展示了如何分配临时缓冲区,并对整个范围内的元素进行了预排序准备。实际的归并步骤被省略了,因为这部分涉及较多内部机制和技术细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值