Algorithm 对以不同方式排序的数组进行排序

Algorithm 对以不同方式排序的数组进行排序,algorithm,sorting,Algorithm,Sorting,我有一个类型为(int,char)的元组数组。它按字典顺序排序: [(0, 'a'), (0, 'b'), (0, 'c'), (1, 'a'), (1, 'b'), (1, 'c') ...] 我需要先按第二个元素排序,然后按第一个元素排序: [(0, 'a'), (1, 'a'), ..., (0, 'b'), (1, 'b'), ..., (0, 'c'), (1, 'c'), ...] 什么样的排序算法最适合这种情况?简短的回答:只需按第二个元素进行排序即可 更长的回答: 使用稳定的

我有一个类型为(int,char)的元组数组。它按字典顺序排序:

[(0, 'a'), (0, 'b'), (0, 'c'), (1, 'a'), (1, 'b'), (1, 'c') ...]
我需要先按第二个元素排序,然后按第一个元素排序:

[(0, 'a'), (1, 'a'), ..., (0, 'b'), (1, 'b'), ..., (0, 'c'), (1, 'c'), ...]
什么样的排序算法最适合这种情况?

简短的回答:只需按
第二个元素进行排序即可

更长的回答:
使用
稳定的
排序算法,首先按
第一个元素
排序,然后按
第二个元素
排序

A保证相等的元素保持相同的顺序

但是,如果您的输入已按
第一个元素排序,则无需再次排序。只需按
第二个元素对其进行稳定排序即可

最著名的稳定排序alg最有可能是
MergeSort

简短回答:只需按
第二个元素进行排序即可

更长的回答:
使用
稳定的
排序算法,首先按
第一个元素
排序,然后按
第二个元素
排序

A保证相等的元素保持相同的顺序

但是,如果您的输入已按
第一个元素排序,则无需再次排序。只需按
第二个元素对其进行稳定排序即可


最著名的稳定排序alg最有可能是
MergeSort

渐进排序,无论您是否以不同的方式对其进行排序,它都没有区别。因此,如果您不关心常数因子,您可以使用任何您喜欢的排序算法。对于这项任务来说,重要的不是使用哪种算法,而是如何应用它。因此,为了示例(在C++中,其他的Langs将提供类似的东西,我猜),我们将只使用<代码> SoTo()/<代码>中的代码>而不是<代码> SoTo()/<代码>。这将为您节省一个常数因子,正如我在一开始所说的,它对渐近运行时间没有任何影响,在任何情况下,它是O(n*log(n))。

渐进地,无论您是否以不同的方式对它进行排序,它都没有影响。因此,如果您不关心常数因子,您可以使用任何您喜欢的排序算法。对于这项任务来说,重要的不是使用哪种算法,而是如何应用它。因此,为了示例(在C++中,其他的Langs将提供类似的东西,我猜),我们将只使用<代码> SoTo()/<代码>中的代码>而不是<代码> SoTo()/<代码>。这将为您节省一个常数因子,正如我在一开始所说的,在任何情况下,这对渐近运行时间O(n*log(n))没有任何影响。

一个简单的方法是:

  • 创建一个集合,将集合中的元组元素放在一起,但“反向”:{1,'a'}=>“a1” (根据具体情况,您可能需要允许插入合适的空格和/或零,例如{1,'a'}=>“a01”,如果字符始终是单字符,但数字可能有两位数字)

  • 分类

  • 重新打开包装


  • 打包/解包步骤是O(n),排序是决定性能的步骤:O(nLogn)

    一个简单的方法是:

  • 创建一个集合,将集合中的元组元素放在一起,但“反向”:{1,'a'}=>“a1” (根据具体情况,您可能需要允许插入合适的空格和/或零,例如{1,'a'}=>“a01”,如果字符始终是单字符,但数字可能有两位数字)

  • 分类

  • 重新打开包装


  • 打包/解包步骤是O(n),排序是决定性能的步骤:O(nLogn)

    您能详细说明一下要求吗?(例如,非常快,不管是什么)以及数字和字符集的性质?(例如,它们是固定大小和连续的吗?)?(例如,非常快,不管是什么)以及数字和字符集的性质?(例如,它们是固定大小和连续的吗?+1取决于Lazin所说的“字典顺序”,元组可能已经按照第一个元素的顺序排序了。在这种情况下,只需要第二种排序,是的,需要一种稳定的排序。当然,我不知道这是否比定义一个新的顺序和使用任何旧的算法更划算。@Patrick87:就目前的答案而言,它绝对不能给你买任何东西-你要排序两次,一次是第一个
    元素,然后是第二个
    元素。如果只按第二个元素排序,可能会节省一点(因为OP说它在开始时已经按第一个元素排序了)。在实践中,这可能会对您有所帮助(如果您保证输入按字典顺序排序)。拥有自定义顺序(以及由此产生的一般解决方案)的开销是一个常数因子(2),因此,渐进地说,仅按第二个元素排序不会给您带来任何好处。@Patrick87当然,当它已按
    第一个元素
    排序时,就不必再次进行排序。我编辑了我的答案。许多像MergeSort这样的“旧”算法是稳定的。作为一名稳定的分拣员,这并不是什么“特别”或“新”的事情我曾经考虑过类似于没有合并阶段的合并排序(因为数组已经合并了)。当然,这会根据需要发挥作用。你在理解排序工作原理时犯了一些根本性的错误。
    MergeSort
    中的所有排序都是在合并阶段完成的。没有合并阶段的合并排序毫无意义。而且无论您使用的是数组还是列表等有序数据结构。这与alg本身无关。除此之外,我不建议自己实施它。只需在库中使用现有的稳定排序,如
    stable\u sort()
    +1,取决于Lazin所说的“字典顺序”,元组可能
    //the tuple
    struct intChar{
        int i;
        char c;
    };
    
    //define how our struct evaluates under '<'
    bool operator<(const intChar &lhs, const intChar &rhs){
        if(lhs.c == rhs.c){
            return lhs.i < rhs.i;
        }
        return lhs.c < rhs.c;
    }
    
    #include <algorithm>
    
    vector<intChar> toSort;
    
    /*... fill vector ...*/
    sort(toSort.begin(), toSort.end());
    
    if(lhs.c == rhs.c){
        return lhs.i < rhs.i;
    }