【问题标题】:Confusion passing an array by reference in recursive sort algorithm在递归排序算法中通过引用传递数组的困惑
【发布时间】:2012-12-13 21:18:38
【问题描述】:

我对通过引用传递数组感到困惑。由于数组存储在堆上,我相信当它们作为参数传递时,参数的值就是堆中的位置。这可能会混淆变量所代表的内容。

  1. 如果数组存储在堆上,那么在将数组传递给方法时,ref 关键字究竟是什么意思?我相信更改被调用方法中的数组会更改调用方法,因为它是按值传递的,并且值包含对数组的引用。

  2. 如果我跳过Sort 而是直接调用DoSort,那么unsortedArray 会正确排序。在下面的程序中,为什么unsortedArray 在执行结束时从不排序?这与这是一个递归算法有关吗?

代码如下:

public class Program {
    static void Main(string[] args) {
        int[] unsortedArray = new[] { 9, 7, 5, 3, 1 };
        Sort(unsortedArray);
    }

    public static void Sort(int[] sortArray) {
        DoSort(ref sortArray);
    }

    public static void DoSort(ref int[] doSortArray) {
        if (doSortArray.Length == 1) {
            return;
        }
        int midpoint = doSortArray.Length / 2;

        // divide the array into the left portion
        int[] left = new int[midpoint];
        for (int i = 0; i < midpoint; i++) {
            left[i] = doSortArray[i];
        }

        // divide the array into the right portion 
        int[] right = new int[doSortArray.Length - midpoint];
        int j = 0;
        for (int i = midpoint; i < doSortArray.Length; i++) {
            right[j] = doSortArray[i];
            j++;
        }

        DoSort(ref left);
        DoSort(ref right);

        doSortArray = Merge(left, right);
    }

    /// <summary>
    /// Merges the specified unmerged array.
    /// </summary>
    /// <param name="left">The left.</param>
    /// <param name="right">The right.</param>
    private static int[] Merge(int[] left, int[] right) {
        int i = 0;
        int[] result = new int[left.Length + right.Length];

        int leftIndex = 0;
        int rightIndex = 0;
        while (leftIndex < left.Length || rightIndex < right.Length) {
            if (leftIndex < left.Length && rightIndex < right.Length) {
                if (left[leftIndex] <= right[rightIndex]) {
                    result[i] = left[leftIndex];
                    leftIndex++;
                } else {
                    result[i] = right[rightIndex];
                    rightIndex++;
                }
            }
            else if (leftIndex < left.Length) {
                result[i] = left[leftIndex];
                leftIndex++;
            }
            else if (rightIndex < right.Length) {
                result[i] = right[rightIndex];
                rightIndex++;
            }
            i++;
        }

        return result;
    }
}

Passing Arrays as Arguments (C# Programming Guide)

【问题讨论】:

  • 查看此问题的最佳答案中包含的链接。 stackoverflow.com/questions/1981916/c-sharp-ref-keyword-usage
  • 您不会通过引用Sort 传递sortArray,而只是传递给DoSort。这就是绕过Sort时它可以正常工作的原因。
  • 这似乎是从其他语言转换而来的。这是对数组进行排序的一种非常低效的方法(在似乎是就地目标的地方进行拆分和合并)。扔掉它。
  • @Henk - 这只是 MergeSort 的教科书示例。我对参数传递比对性能更好奇。这不会进入生产代码!感谢您的考虑。

标签: c# algorithm sorting


【解决方案1】:

这就是区别:

int[] array = null;
DoSort(array)
//array is still null

DoSort(int[] array)
{
 array = new int[10];
}

...

int[] array = null;
DoSort(ref array)
//array is new int[10]

DoSort(ref int[] array)
{
 array = new int[10];
}

在任何一种情况下,您都可以更改数组的内容。 只有通过引用传递,才能在调用者中改变引用的实际值。

因为这条线,您的示例需要ref

doSortArray = Merge(left, right);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-02
    • 2012-10-10
    • 2020-10-02
    • 2015-10-19
    • 2019-11-11
    • 2016-03-25
    • 1970-01-01
    相关资源
    最近更新 更多