我读了此post about card shuffling,在许多改组和排序算法中,您需要交换列表或数组中的两个项目。但是,一种有效且高效的Swap方法是什么样的?
假设T[]
和List<T>
。您如何最好地实现在这两个项目中交换两个项目的方法?
Swap(ref cards[i], ref cards[n]); // How is Swap implemented?
[好,您发布的代码(ref cards[n]
)只能与数组(而不是列表)一起使用-但您可以简单地使用(其中foo
和bar
是两个值):
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;
}
((使它通用)将是微不足道的-但是,在数组上工作的原始“内联”版本(即,不是方法)会更快。
用途:
void swap(int &a, int &b)
{
// &a != &b
// a == b OK
a ^= b;
b ^= a;
a ^= b;
return;
}
我没有意识到我在C#部分中。这是C ++代码,但应该具有相同的基本思想。我相信^在C#中也是XOR。看起来好像不需要&
,您可能需要“ ref”(?)。我不确定。
良好的交换是您不交换内容的交换。在C / C ++中,这类似于交换指针而不是交换内容。这种交换方式很快,并带有一些例外保证。不幸的是,我的C#太生锈了,无法将其放入代码中。对于简单的数据类型,此样式不能给您太多帮助。但是一旦您习惯了并且不得不处理更大(或更复杂)的对象,它便可以挽救您的生命。
那呢?这是交换方法的通用实现。 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洛伦佐
对于任何想知道的人,也可以使用扩展方法(.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);
11年后,我们有元组...
(foo, bar) = (bar, foo);