如何降低排序的时间复杂度?
Posted
技术标签:
【中文标题】如何降低排序的时间复杂度?【英文标题】:How to decrease time complexity of sorting? 【发布时间】:2012-08-13 17:31:10 【问题描述】:我已经编写了这个排序代码,它运行得很好。我想知道如何降低它的时间复杂度。
#include <iostream>
using namespace std;
void sort(int a[], int n)
int min, temp;
for(int i=0;i<n-1;i++)
min=i;
for(int j=i+1;j<n;j++)
if(a[min]>a[j])
min=j;
temp=a[i];
a[i]=a[min];
a[min]=temp;
for(int i=0;i<n;i++)
cout<<a[i]<<endl;
int main()
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
cin>>arr[i];
sort(arr,n);
return 0;
如果没有其他方法可以更改它,那么我是否必须更改算法?如果是,请推荐一个算法?
谢谢。
【问题讨论】:
这是作业吗?你有没有描述过你日常工作的复杂性? 自己做。这就是为什么我没有要求代码,只要求算法名称,因为它类似于作业问题.m:) @MichaelBurr 只是想知道答案是否重要? @Артём Царионов:我认为人们经常以不同的方式回答基于家庭作业的问题。例如,避免简单地“给出答案”或将答案更多地定位于基本面。至于表征当前例程的复杂性 - 在您了解当前情况(至少在某种程度上)之前,您如何知道您是否已经改进了一些事情? @MichaelBurr 好点子,我一直不明白为什么人们关心它是否是家庭作业 【参考方案1】:您似乎使用了某种选择排序,这种方法众所周知很慢。 IRL 应用程序通常使用quicksort 或merge-sort(不是后者)。
我建议你也这样做(假设这是出于教育目的)。
否则,使用<algorithm>
中定义的std::sort
。
另外,请注意您的代码不是标准的:
cin>>n;
int arr[n];
C++ 不支持 VLA。你最好改用std::vector
。如果您使用 C++,请不要编写 C 代码。
【讨论】:
VLA 是?变长数组? @LuchianGrigore- std::sort 使用哪种算法对数组进行排序? @PrakharMohan idk 如果它被强制执行。来自链接:Complexity Approximately N*logN comparisons on average (where N is last-first). In the worst case, up to N^2, depending on specific sorting algorithm used by library implementation.
来自"depending"
我认为该标准并未强制执行特定算法,而是遵守复杂性要求的算法。
后一优先是什么意思?这就是我想知道的?该库使用哪种算法?正是我的问题。 :)
@PrakharMohan:“STL 的 list::sort() 使用了哪种排序算法?” - ***.com/questions/1717773/…【参考方案2】:
您的算法是选择排序,一种O(n^2)
算法:如果输入大小在n
中线性增长,则运行时间与n
的二次函数成正比。基于任意输入(即没有关于输入的先验知识)的比较排序的最小时间复杂度为O(n log n)
。 STL 函数std::sort
提供了这种保证。
#include <algorithm>
#include <vector>
int main()
int n;
cin>>n;
std::vector<int> arr;
arr.resize(n);
for(int i=0;i<n; ++i) // ++i rather than i++ is a good habit to get into
cin>>arr[i];
// O(N log N) complexity
std::sort(arr.begin(), arr.end());
return 0;
对于小的输入,选择排序(或插入排序)有时可以足够快。您也可以在 C++11 中将其编码为几行代码(它使用 lambda 表达式)
#include <algorithm>
#include <iterator>
template<class ForwardIterator>
void selection_sort(ForwardIterator first, ForwardIterator last)
std::for_each(first, last, [](ForwardIterator it) // your outer loop
auto const selection = std::min_element(it, last); // your inner loop
std::iter_swap(selection, it); // your swap code
);
// call on your vector
selection_sort(arr.begin(), arr.end());
从这段代码中,选择排序的工作原理也一目了然:重复地在数组的剩余部分中找到最小元素,并将其交换到位。它应该等同于您自己的代码,但我希望您同意它更容易理解(也就是说,一旦您了解了 STL)。
【讨论】:
您好!我不想用这个评论冒犯你,但是:1)如果这是出于教育目的,你并没有通过提供完整的解决方案来帮助他。 2) 代码无效,因为 C++ 不支持变长数组。reserve
应该是resize
,否则你有未定义的行为。此外,您对 std::sort
的调用是为数组编写的,但现在您使用的是向量。【参考方案3】:
您正在使用Selection sort 对数组进行排序。该算法的运行时间 id O(n^2)
。您可以使用Merge sort或Heap Sort对运行时间为O(nlog(n))
的排序。
您还可以使用Intro Sort,它使用一个非常巧妙的技巧将QuickSort's 最坏情况下推到 O(n log n),同时保持其他良好的性能特征
查看wiki page on sorting algorithms了解更多详情。
【讨论】:
在实践中,快速排序是最有效的。 @LuchianGrigore:对于实际上太常见的情况,快速排序具有可怕的最坏情况。通常最好使用组合,例如 introsort。 实际上,快速排序不再被认为是普通案例排序之王,尽管那是我上大学的时候。现在,Python 和 Java 都切换到了 timsort,这是一个经过很好修改的合并排序,因此合并步骤已经到位。以上是关于如何降低排序的时间复杂度?的主要内容,如果未能解决你的问题,请参考以下文章