在递归排序算法中通过引用传递数组的混乱

时间:2012-12-13 21:18:39

标签: c# algorithm sorting

我对通过引用传递数组感到困惑。由于数组存储在堆上,因此我认为当它们作为参数传递时,参数的值是堆中的位置。这可能是变量代表什么的混淆。

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

  2. 如果我跳过Sort而是直接致电DoSort,则会unsortedArray正确排序。在下面的程序中,为什么unsortedArray在执行结束时从未排序?这是否与递归算法有关?

  3. 以下是代码:

    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)

1 个答案:

答案 0 :(得分:2)

区别在于:

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);