如何在C#中通过引用传递
How to pass by reference in C#
我正在编写一个快速排序 class 模仿 Sedgewick 在 "Algorithms 4" 中给出的代码。原代码写在Java。我用 C# 翻译了核心部分,但它似乎不起作用。问题似乎出在 a = a.OrderBy(x => r.Next()).ToArray()
行,但我不知道如何更正它。
我尝试在 Sort
和 Partition
方法签名中添加 ref
但是一旦我在 Main
中调用函数 Sort(ref a)
,编译器cannot converte ref System.String[] to ref System.IComparable[]
的投诉。
我还尝试使第一个 Sort
return 成为 IComparable[]
排序数组。但是,当我在 Main
中像这样 string[] nums = (string[]) Sort(nums)
调用它时,它会抛出一个运行时错误 Unable to cast object of type 'System.IComparable[]' to type 'System.String[]'.
public class Quick
{
public static void Sort(IComparable[] a)
{
Random r = new Random();
a = a.OrderBy(x => r.Next()).ToArray();
Sort(a, 0, a.Length - 1);
}
private static void Sort(IComparable[] a, int lo, int hi)
{
if (lo >= hi) return;
int p = Partition(a, lo, hi);
Sort(a, lo, p - 1);
Sort(a, p + 1, hi);
}
private static int Partition(IComparable[] a, int lo, int hi)
{
int i = lo, j = hi;
IComparable p = a[lo];
while (true)
{
while (Less(a[++i], p))
{
if (i == hi)
break;
}
while (Less(p, a[--j]))
{
if (j == lo)
break;
}
if (i >= j) break;
Exch(a, i, j);
}
Exch(a, lo, j);
return j;
}
private static void Exch(IComparable[] a, int lo, int hi)
{
IComparable tmp = a[lo];
a[lo] = a[hi];
a[hi] = tmp;
}
private static bool Less(IComparable a, IComparable b)
{
return a.CompareTo(b) < 0;
}
public static void Main(string[] args)
{
string[] nums = File.ReadAllLines(args[0]);
for (int i = 0; i < nums.Length; i++)
{
Console.WriteLine(nums[i]);
}
Sort(nums);
Console.WriteLine("After sorting:");
for (int i = 0; i < nums.Length; i++)
{
Console.WriteLine(nums[i]);
}
Console.ReadKey();
}
}
第二个 WriteLine 应该打印出排序后的数组,但它没有。
您需要 return 排序数组,因为正如您所说,它是按值而不是按引用传递的。
添加 return 类型而不是 void 到 Sort 方法和 return a;
并改变
排序(nums);
至
nums=排序(nums);
这里的问题不是引用传递,而是这一行,正如你所确定的:
a = a.OrderBy(x => r.Next()).ToArray();
您正在给 a
一个新值,这不同于仅仅修改 a
的内容。由于 Sort
方法对数组进行就地排序,因此您不应创建新数组,并且在排序之前不必对数组进行洗牌。
因此,删除这两行应该会使您的代码正常工作:
Random r = new Random();
a = a.OrderBy(x => r.Next()).ToArray();
当您尝试 return 来自 Sort
的数组时,您似乎遇到了一些问题。您可以通过将所有方法设为通用来解决此问题,并将通用参数 T
限制为 IComparable<T>
:
public static T[] Sort<T>(T[] a) where T: IComparable<T>
{
Random r = new Random();
a = a.OrderBy(x => r.Next()).ToArray();
Sort(a, 0, a.Length - 1);
return a;
}
private static void Sort<T>(T[] a, int lo, int hi) where T: IComparable<T>
{
if (lo >= hi) return;
int p = Partition(a, lo, hi);
Sort(a, lo, p - 1);
Sort(a, p + 1, hi);
}
private static int Partition<T>(T[] a, int lo, int hi) where T: IComparable<T>
{
int i = lo, j = hi;
T p = a[lo];
while (true)
{
while (Less(a[++i], p))
{
if (i == hi)
break;
}
while (Less(p, a[--j]))
{
if (j == lo)
break;
}
if (i >= j) break;
Exch(a, i, j);
}
Exch(a, lo, j);
return j;
}
private static void Exch<T>(T[] a, int lo, int hi)
{
T tmp = a[lo];
a[lo] = a[hi];
a[hi] = tmp;
}
private static bool Less<T>(T a, T b) where T: IComparable<T>
{
return a.CompareTo(b) < 0;
}
我正在编写一个快速排序 class 模仿 Sedgewick 在 "Algorithms 4" 中给出的代码。原代码写在Java。我用 C# 翻译了核心部分,但它似乎不起作用。问题似乎出在 a = a.OrderBy(x => r.Next()).ToArray()
行,但我不知道如何更正它。
我尝试在 Sort
和 Partition
方法签名中添加 ref
但是一旦我在 Main
中调用函数 Sort(ref a)
,编译器cannot converte ref System.String[] to ref System.IComparable[]
的投诉。
我还尝试使第一个 Sort
return 成为 IComparable[]
排序数组。但是,当我在 Main
中像这样 string[] nums = (string[]) Sort(nums)
调用它时,它会抛出一个运行时错误 Unable to cast object of type 'System.IComparable[]' to type 'System.String[]'.
public class Quick
{
public static void Sort(IComparable[] a)
{
Random r = new Random();
a = a.OrderBy(x => r.Next()).ToArray();
Sort(a, 0, a.Length - 1);
}
private static void Sort(IComparable[] a, int lo, int hi)
{
if (lo >= hi) return;
int p = Partition(a, lo, hi);
Sort(a, lo, p - 1);
Sort(a, p + 1, hi);
}
private static int Partition(IComparable[] a, int lo, int hi)
{
int i = lo, j = hi;
IComparable p = a[lo];
while (true)
{
while (Less(a[++i], p))
{
if (i == hi)
break;
}
while (Less(p, a[--j]))
{
if (j == lo)
break;
}
if (i >= j) break;
Exch(a, i, j);
}
Exch(a, lo, j);
return j;
}
private static void Exch(IComparable[] a, int lo, int hi)
{
IComparable tmp = a[lo];
a[lo] = a[hi];
a[hi] = tmp;
}
private static bool Less(IComparable a, IComparable b)
{
return a.CompareTo(b) < 0;
}
public static void Main(string[] args)
{
string[] nums = File.ReadAllLines(args[0]);
for (int i = 0; i < nums.Length; i++)
{
Console.WriteLine(nums[i]);
}
Sort(nums);
Console.WriteLine("After sorting:");
for (int i = 0; i < nums.Length; i++)
{
Console.WriteLine(nums[i]);
}
Console.ReadKey();
}
}
第二个 WriteLine 应该打印出排序后的数组,但它没有。
您需要 return 排序数组,因为正如您所说,它是按值而不是按引用传递的。 添加 return 类型而不是 void 到 Sort 方法和 return a;
并改变
排序(nums);
至
nums=排序(nums);
这里的问题不是引用传递,而是这一行,正如你所确定的:
a = a.OrderBy(x => r.Next()).ToArray();
您正在给 a
一个新值,这不同于仅仅修改 a
的内容。由于 Sort
方法对数组进行就地排序,因此您不应创建新数组,并且在排序之前不必对数组进行洗牌。
因此,删除这两行应该会使您的代码正常工作:
Random r = new Random();
a = a.OrderBy(x => r.Next()).ToArray();
当您尝试 return 来自 Sort
的数组时,您似乎遇到了一些问题。您可以通过将所有方法设为通用来解决此问题,并将通用参数 T
限制为 IComparable<T>
:
public static T[] Sort<T>(T[] a) where T: IComparable<T>
{
Random r = new Random();
a = a.OrderBy(x => r.Next()).ToArray();
Sort(a, 0, a.Length - 1);
return a;
}
private static void Sort<T>(T[] a, int lo, int hi) where T: IComparable<T>
{
if (lo >= hi) return;
int p = Partition(a, lo, hi);
Sort(a, lo, p - 1);
Sort(a, p + 1, hi);
}
private static int Partition<T>(T[] a, int lo, int hi) where T: IComparable<T>
{
int i = lo, j = hi;
T p = a[lo];
while (true)
{
while (Less(a[++i], p))
{
if (i == hi)
break;
}
while (Less(p, a[--j]))
{
if (j == lo)
break;
}
if (i >= j) break;
Exch(a, i, j);
}
Exch(a, lo, j);
return j;
}
private static void Exch<T>(T[] a, int lo, int hi)
{
T tmp = a[lo];
a[lo] = a[hi];
a[hi] = tmp;
}
private static bool Less<T>(T a, T b) where T: IComparable<T>
{
return a.CompareTo(b) < 0;
}