12

我读过这篇关于洗牌的文章,在许多洗牌和排序算法中,您需要交换列表或数组中的两个项目。但是一个好的高效的 Swap 方法是什么样的呢?

让我们说 aT[]和 a List<T>。您将如何最好地实现一种在这两个项目中交换两个项目的方法?

Swap(ref cards[i], ref cards[n]);   // How is Swap implemented?
4

7 回答 7

27

好吧,您发布的代码 ( ref cards[n]) 只能与数组(而不是列表)一起使用 - 但您可以简单地使用(其中foobar是两个值):

static void Swap(ref int foo, ref int bar) {
    int tmp = foo;
    foo = bar;
    bar = tmp;
}

或者可能(如果你想要原子):

Interlocked.Exchange(ref foo, ref bar);

不过,就我个人而言,我认为我不会打扰交换方法 - 直接进行即可;这意味着您可以使用(对于列表或数组):

int tmp = cards[n];
cards[n] = cards[i];
cards[i] = tmp;

如果您真的想编写一个适用于列表数组的交换方法,则必须执行以下操作:

static void Swap(IList<int> list, int indexA, int indexB)
{
    int tmp = list[indexA];
    list[indexA] = list[indexB];
    list[indexB] = tmp;
}

(使这个通用化是微不足道的) - 但是,在数组上工作的原始“内联”版本(即不是方法)会更快。

于 2009-02-16T09:34:36.620 回答
3

一个好的交换是你不交换内容的地方。在 C/C++ 中,这类似于交换指针而不是交换内容。这种交换方式很快并且带有一些异常保证。不幸的是,我的 C# 太生锈了,无法将其放入代码中。对于简单的数据类型,这种风格并没有给你太多。但是,一旦您习惯并且必须处理更大(更复杂)的对象,它就可以挽救您的生命。

于 2009-02-16T09:37:12.807 回答
3

那这个呢?它是交换方法的通用实现。Jit 将为您的封闭类型创建一个编译版本,因此您不必担心性能!

/// <summary>
/// Swap two elements
/// Generic implementation by LMF
/// </summary>
public static void Swap<T>(ref T itemLeft, ref T itemRight) {
    T dummyItem = itemRight;
    itemLeft = itemRight;
    itemRight = dummyItem;
}

HTH 洛伦佐

于 2013-12-20T03:41:30.500 回答
3

11 年后,我们有了元组......

(foo, bar) = (bar, foo);
于 2020-01-26T02:29:56.630 回答
2

采用:

void swap(int &a, int &b)
{
    // &a != &b
    // a == b OK
    a ^= b;
    b ^= a;
    a ^= b;
    return;
}

我没有意识到我在 C# 部分。这是 C++ 代码,但它应该具有相同的基本思想。我相信 ^ 在 C# 中也是 XOR。看起来&你可能需要“ref”(?)。我不确定。

于 2010-01-03T22:17:08.580 回答
0

您现在可以使用元组来完成此交换,而无需手动声明临时变量:

static void Swap<T>(ref T foo, ref T bar)
{
    (foo, bar) = (bar, foo)
}
于 2021-09-02T22:09:26.330 回答
-1

对于任何想知道的人,也可以使用扩展方法(.NET 3.0 和更高版本)进行交换。

一般来说,似乎不可能说扩展方法“this”的值是 ref,因此您需要返回它并覆盖旧值。

public static class GeneralExtensions {
    public static T SwapWith<T>(this T current, ref T other) {
        T tmpOther = other;
        other = current;
        return tmpOther;
    }
}

然后可以像这样使用此扩展方法:

int val1 = 10;
int val2 = 20;    
val1 = val1.SwapWith(ref val2);
于 2014-01-20T15:16:53.480 回答