在 C# 中对整数三元组数组进行排序

Posted

技术标签:

【中文标题】在 C# 中对整数三元组数组进行排序【英文标题】:Sort array of integer-triples in C# 【发布时间】:2021-06-18 14:16:10 【问题描述】:

我有一个由三元组组成的整数数组。

[a1, b1, c1, a2, b2, c2, ... ,aN, bN, cN]

每个元组 (ai, bi) 都是唯一的,无论三元组 (a i, bi, ci).

我想按 ai 的值升序对数组进行排序,然后按 bi 的值升序。

当然,我可以引入一个结构 Triple,创建一个 Triple 实例的数组,然后使用自定义排序器对其进行排序,但这会占用大量内存并提高性能开销。

如何在整数数组中对其进行排序?

【问题讨论】:

按三排序:即每次迭代,您一次移动和操作 3 个整数。 我很好奇为什么你认为与 3x 整数的集合相比,三个整数结构的集合会使用更多的内存并花费更多的机器周期来排序? 因为我必须首先创建它们。我已经有了整数数组。 编写一个类型,作为数组中三个整数的外观,但看起来和闻起来像一个三整数元组。 您真的想编写一个自定义的Sort 实现,将数组的每个连续三元组视为一个不同的实体吗?正确书写such code 不适合胆小的人。如果我在你的位置,我会强烈考虑支付额外的数组分配成本,以避免编写如此复杂且容易出错的代码。 【参考方案1】:

这是一种对由连续三元组组成的数组进行排序的方法,应该非常有效。每个排序操作分配一个辅助int[] indices 数组,其大小为源数组的三分之一。对这个辅助数组进行排序,将较大源数组上的交换操作减少到绝对最小值(最多 N - 1 次交换)。

public static void SortTriplets<T>(T[] source, Comparison<(T, T, T)> comparison)

    // Create an array of incremental indices (zero based)
    var indices = new int[source.Length / 3];
    for (int i = 0; i < indices.Length; i++) indices[i] = i;

    // Sort the indices according to the source array and the comparison delegate
    Array.Sort<int>(indices, (a, b) =>
    
        a *= 3;
        b *= 3;
        return comparison(
            (source[a], source[a + 1], source[a + 2]),
            (source[b], source[b + 1], source[b + 2]));
    );

    // Rearrange the source array according to the sorted indices
    for (int i = 0; i < indices.Length - 1; i++)
    
        int k = indices[i];
        while (k < i) k = indices[k];
        if (k == i) continue;
        Swap(i, k);
    

    void Swap(int a, int b)
    
        a *= 3;
        b *= 3;
        (T, T, T) temp = (source[a], source[a + 1], source[a + 2]);
        source[a] = source[b];
        source[a + 1] = source[b + 1];
        source[a + 2] = source[b + 2];
        source[b] = temp.Item1;
        source[b + 1] = temp.Item2;
        source[b + 2] = temp.Item3;
    

使用示例:

var random = new Random();
int[] source = Enumerable.Range(1, 15).Select(_ => random.Next(1, 6)).ToArray();
Console.WriteLine($"Source: String.Join(", ", source)");
SortTriplets(source, (a, b) =>

    int ret = Comparer<int>.Default.Compare(a.Item1, b.Item1);
    if (ret == 0) ret = Comparer<int>.Default.Compare(a.Item2, b.Item2);
    return ret;
);
Console.WriteLine($"Sorted: String.Join(", ", source)");

输出:

Source: 3, 2, 3, 2, 2, 1, 2, 3, 2, 5, 4, 2, 1, 5, 4
Sorted: 1, 5, 4, 2, 2, 1, 2, 3, 2, 3, 2, 3, 5, 4, 2

Try it on Fiddle.

【讨论】:

太棒了。而且速度很快!我印象深刻,谢谢!

以上是关于在 C# 中对整数三元组数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

三数之和

在Java中对数组进行排序

在 C# 中对对象列表进行排序

如何在 Python 中就地对整数数组进行排序?

c_cpp 给定一个整数数组,找到三元组,使得a ^ 2 + b ^ 2 = c ^ 2。

如何在javascript中对字符串进行数字排序