【问题标题】: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 好点子,我一直不明白为什么人们关心它是否是家庭作业

标签: c++ algorithm sorting time-complexity


【解决方案1】:

您似乎使用了某种选择排序,这种方法众所周知很慢。 IRL 应用程序通常使用quicksortmerge-sort(不是后者)。

我建议你也这样做(假设这是出于教育目的)。

否则,使用&lt;algorithm&gt; 中定义的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() 使用了哪种排序算法?” - stackoverflow.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 sortHeap Sort对运行时间为O(nlog(n))的排序。
您还可以使用Intro Sort,它使用一个非常巧妙的技巧将QuickSort's 最坏情况下推到 O(n log n),同时保持其他良好的性能特征

查看wiki page on sorting algorithms了解更多详情。

【讨论】:

  • 在实践中,快速排序是最有效的。
  • @LuchianGrigore:对于实际上太常见的情况,快速排序具有可怕的最坏情况。通常最好使用组合,例如 introsort。
  • 实际上,快速排序不再被认为是普通案例排序之王,尽管那是我上大学的时候。现在,Python 和 Java 都切换到了 timsort,这是一个经过很好修改的合并排序,因此合并步骤已经到位。
猜你喜欢
  • 2012-07-28
  • 2016-01-08
  • 1970-01-01
  • 2020-09-15
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 2020-01-16
相关资源
最近更新 更多