如何在C#中通过引用传递

How to pass by reference in C#

我正在编写一个快速排序 class 模仿 Sedgewick 在 "Algorithms 4" 中给出的代码。原代码写在Java。我用 C# 翻译了核心部分,但它似乎不起作用。问题似乎出在 a = a.OrderBy(x => r.Next()).ToArray() 行,但我不知道如何更正它。

我尝试在 SortPartition 方法签名中添加 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;
}