【问题标题】:Generic Mergesort in C#C# 中的通用合并排序
【发布时间】:2013-08-11 00:24:30
【问题描述】:

我正在尝试在C# 中实现一个通用的Mergesort 算法,但我在使用Constraints 时遇到了困难。我搜索了很多参考资料,但找不到任何像我这样实现算法的参考资料。

MergeSort algorithm in C#

Generic Implementation of Sorting Algorithms

无论如何,我正在尝试提供一种实现,它只允许用户对继承自 IComparable 接口的数据集进行合并排序。

以下是我目前所拥有的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SortUtil
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> testList = new List<int> { 1, 5, 2, 7, 3, 9, 4, 6 };
            Mergesort.mergeSort<int>(testList); // Compiler Error at this Line.
        }
    }
    class Mergesort
    {   
        public static void mergeSort<T>(ref List<T> inputData)
            where T: IComparable<T>
        {
            mergeSort(ref inputData, 0, inputData.Count - 1);
        }

        private static void mergeSort<T>(ref List<T> inputData, int firstIndex, int lastIndex)
            where T: IComparable<T>
        {
            // If the firstIndex is greater than the lastIndex then the recursion 
            // has divided the problem into a single item. Return back up the call 
            // stack.
            if (firstIndex >= lastIndex)
                return;

            int midIndex = (firstIndex + lastIndex) / 2;

            // Recursively divide the first and second halves of the inputData into
            // its two seperate parts.
            mergeSort(ref inputData, firstIndex, midIndex);
            mergeSort(ref inputData, midIndex + 1, lastIndex);

            // Merge the two remaining halves after dividing them in half.
            merge(ref inputData, firstIndex, midIndex, lastIndex);
        }

        private static void merge<T>(ref List<T> inputData, int firstIndex, int midIndex, int lastIndex)
            where T: IComparable<T>
        {
            int currentLeft = firstIndex;
            int currentRight = midIndex + 1;

            T[] tempData = new T[(lastIndex - firstIndex) + 1];
            int tempPos = 0;

            // Check the items at the left most index of the two havles and compare
            // them. Add the items in ascending order into the tempData array.
            while (currentLeft <= midIndex && currentRight <= lastIndex)
                if (inputData.ElementAt(currentLeft).CompareTo(inputData.ElementAt(currentRight)) < 0)
                {
                    tempData[tempPos++] = inputData.ElementAt(currentLeft++);
                }
                else
                {
                    tempData[tempPos++] = inputData.ElementAt(currentRight++);
                }

            // If there are any remaining items to be added to the tempData array,
            // add them.

            while (currentLeft <= midIndex)
            {
                tempData[tempPos++] = inputData.ElementAt(currentLeft++);
            }

            while (currentRight <= lastIndex)
            {
                tempData[tempPos++] = inputData.ElementAt(currentRight++);
            }

            // Now that the items have been sorted, copy them back into the inputData
            // reference that was passed to this function.
            tempPos = 0;
            for (int i = firstIndex; i <= lastIndex; i++) {
                inputData.Insert(firstIndex, tempData.ElementAt(tempPos));
            }
        }
    }
}

My issue: 我在 Program 类的 Main 方法中遇到编译器错误;但是,当我静态调用 mergeSort 函数时,我不应该为它提供参数化类型吗?

我收到错误"The best overloaded method match for... has some invalid arguments."

我将不胜感激任何实施建议和/或纠正此错误的任何方式。请注意,我最喜欢使用 Java,而且由于 C# 不直接支持通配符,这种方法对我来说是陌生的。对此的任何解释也将不胜感激。

【问题讨论】:

  • 删除ref 的所有用法并照常进行。 ref 使用 Call By Reference 语义(即,对变量的 assignments 将反映在调用者中),而 C# 通常(并且在此处充分)使用 Call By (Object) Sharing 语义。请记住,当引用类型被传递时,它被复制/克隆/复制。有关ref/out 何时有用的示例,请参阅int.TryParse

标签: c# sorting constraints mergesort


【解决方案1】:

您可以从所有参数中删除ref,因为您似乎没有使用它的功能。

此外,在大多数情况下,您不需要提供泛型参数类型,因为编译器会为您推断类型。所以这在大多数情况下应该可以工作(假设你已经从参数中删除了ref):

Mergesort.mergeSort(testList);

List&lt;T&gt; 和数组也有索引器,因此您可以通过inputData[index] 而不是ElementAt 获取特定元素。这样打字就少了。

【讨论】:

  • 确实如此。最好不要使用ref(尤其是当行为不被理解/不需要时)。我见过很多人添加它,因为他们认为它“传递了对 .. 的引用”,允许共享修改或类似的东西 - 也许来自 VBA 背景?
  • 感谢您的提示!我很感激。
【解决方案2】:

MergeSort 需要ref 参数,所以它需要ref 关键字。这应该有效:

Mergesort.mergeSort<int>(ref testList);  

ref 关键字导致参数通过引用传递,而不是通过 价值。通过引用传递的效果是对 方法中的参数反映在底层参数中 调用方法中的变量。参考参数的值为 始终与基础参数变量的值相同。

【讨论】:

  • 很好,蒂姆!那个让我眼花缭乱。
猜你喜欢
  • 2015-03-27
  • 1970-01-01
  • 1970-01-01
  • 2013-01-06
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 2011-02-09
  • 2013-03-27
相关资源
最近更新 更多