使用数组和链表进行选择排序的区别
Difference between selection sort with array and linked list?
我想知道使用findmax的数组和findmin的链表进行选择排序背后的逻辑是什么。两者的最佳和最坏情况?
TL;DR
选择排序通常不好。合并排序一般来说是好的,但对于随机访问容器可以通过std::sort
进行改进,对于基于节点的容器可以通过成员函数sort()
进行改进。
选择排序按二次方缩放
考虑以下selection_sort
的通用版本
template<class ForwardIt, class Compare = std::less<typename std::iterator_traits<ForwardIt>::value_type>>
void selection_sort(ForwardIt first, ForwardIt last, Compare cmp = Compare())
{
for (auto it = first; it != last; ++it) {
auto const selection = std::min_element(it, last, cmp);
std::iter_swap(selection, it);
}
}
在长度为N
的std::array
和std::list
上,这都具有O(N^2)
的复杂度:外环处理所有N
元素,对std::min_element
的内部调用也是线性复杂度,这给出了整体的二次缩放。
然而,由于基于比较的排序可以像O(N log N)
一样便宜地完成,这对于大型N
来说是典型的不可接受的缩放。正如@EJP所提到的,选择排序的一个可取之处是,尽管它进行O(N^2)
比较,但它只进行O(N)
数据交换。然而,对于非常大的N
,与大多数O(N log N)
排序算法相比,这种优势最终将被O(N^2)
的比较成本所淹没。
通用合并排序拯救
考虑以下merge_sort
的通用版本
template<class BiDirIt, class Compare = std::less<typename std::iterator_traits<BiDirIt>::value_type>>
void merge_sort(BiDirIt first, BiDirIt last, Compare cmp = Compare())
{
auto const N = std::distance(first, last);
if (N < 2) return;
auto middle = first + N / 2;
merge_sort(first, middle, cmp);
merge_sort(middle, last, cmp);
std::inplace_merge(first, middle, last, cmp);
}
在长度为N
的std::array
和std::list
上,这都具有O(N log N)
复杂性:递归深度为O(log N)
(因为每次间隔都被减半),对std::inplace_merge
的调用具有线性复杂性,这给出了O(N log N)
的整体缩放。
然而,几乎任何严肃的排序算法竞争者都不会因为比较的数量而显著区分自己,而是因为访问和放置数据的相关开销。这样的优化只能用比通用版本更多的知识来完成。
随机访问容器可以受益于混合算法
使用混合算法可以更便宜地对具有随机访问迭代器的容器进行排序。来自标准库的std::sort()
和std::stable_sort
函数提供了O(N log N)
最坏情况复杂度的这种混合算法。通常,它们被实现为IntroSort,它将递归随机枢轴快速排序与堆排序和插入排序混合在一起,这取决于各种递归排序的子范围的大小。
基于节点的容器可以受益于成员函数sort()
基于比较的排序算法大量使用复制或交换迭代器指向的底层数据。对于常规容器,交换底层数据是最好的选择。对于基于节点的容器,如std::list
或std::forward_list
,您更喜欢splice
:只重新排列节点指针,避免复制潜在的大量数据。然而,这需要了解迭代器之间的连接。
这就是std::list
和std::forward_list
都具有成员函数sort()
的原因:它们具有相同的O(N log N)
最坏情况复杂性,但利用了容器基于节点的特性。
- C++选择排序算法中的逻辑错误
- 高级选择排序 - 在一次迭代中搜索两个元素
- 选择排序C++(已修改)并非适用于所有情况
- C++为什么我的指针选择排序中存在分段错误?
- 为什么这个选择排序算法仍然切换一个元素,当它已经是其他元素中最小的元素时?
- 选择排序时交换函数调用的数量和完成的交换次数是否相同?
- 如何使用cpp编写选择排序算法以降序对元素列表进行排序?
- 使用选择排序对数组数据结构进行排序,但它不起作用
- c++ 选择排序在特定情况下不起作用
- 修改的选择排序,选择最大的数字,然后交换到最后
- 如何选择排序一些结构
- 选择排序以查找未排序数组中的最大数字
- 我的选择排序代码是否存在导致它跳过数组中的元素的问题?
- 给定数组范围的选择排序问题
- 选择排序算法生成无序结果
- 使用C 中的一系列字符串的选择排序
- 从递归向后选择排序函数调用 max 和交换函数
- 为 STL 列表编写选择排序
- 跟踪选择排序中的交换和比较次数
- 字母选择排序程序的问题