【问题标题】:MergeSort algorithm in c#C#中的合并排序算法
【发布时间】:2013-03-27 23:30:13
【问题描述】:

我为合并类编写了以下代码:

class Merge
{

    public static void sort(IComparable[] a)
    {
        sort(a, 0, a.Length);
    }

    public static void sort(IComparable[] a, int low, int high)
    {
        int N = high - low;
        if (N <= 1)
            return;

        int mid = low + N / 2;

        sort(a, low, mid);
        sort(a, mid, high);

        IComparable[] aux = new IComparable[N];
        int i = low, j = mid;
        for (int k = 0; k < N; k++)
        {
            if (i == mid) aux[k] = a[j++];
            else if (j == high) aux[k] = a[i++];
            else if (a[j].CompareTo(a[i]) < 0) aux[k] = a[j++];
            else aux[k] = a[i++];
        }

        for (int k = 0; k < N; k++)
        {
            a[low + k] = aux[k];
        }
    }

    private static Boolean isSorted(IComparable[] a)
    {
        for (int i = 1; i < a.Length; i++)
            if (a[i].CompareTo(a[i - 1]) < 0) return false;
        return true;
    }

}

下面的代码是实现。我认为下面的代码应该没有错!但它没有编译...

class Program
{
    static void Main(string[] args)
    {
    Merge ms = new Merge();

    Double[] MyArray = { 80,10,52,7,36,7,67,1,8,54 };
    Console.WriteLine("first array is: \n");
    for (int k = 0; k < MyArray.Length; k++)
    {
        Console.Write(MyArray[k]);
        if (k<9)
           Console.Write(" , ");
    }
    ms.sort(MyArray);  // Error is here. Does't compile !!!
    Console.WriteLine("\n");
    Console.WriteLine("\nsorted array is: \n ");
    for (int k = 0; k < MyArray.Length; k++)
    {
        Console.Write(MyArray[k]);
        if (k<9)
           Console.Write(" , ");
    }
    Console.ReadLine();
    }
}

它无法编译。错误在 ms.sort(MyArray); 中。 我究竟做错了什么? 请带我...

问候

【问题讨论】:

  • 尝试调用 MyArray.sort();没关系-我认为这是一种扩展方法...如果您适当地更改签名-添加“this”关键字,您可以扩展数组对象。
  • 我有两个错误。第一个:Error 1 The best overloaded method match for 'MergeSort.Merge.sort(System.IComparable[])' has some invalid arguments c:\users\hamed\documents\visual studio 2010\Projects\MergeSort\MergeSort\Program.cs 22 9 MergeSort ,第二个是Error 2 Argument 1: cannot convert from 'double[]' to 'System.IComparable[]' c:\users\hamed\documents\visual studio 2010\Projects\MergeSort\MergeSort\Program.cs 22 17 MergeSort

标签: c# algorithm console mergesort


【解决方案1】:

这段代码有两个问题:

  1. 签名不匹配,IComparable[]在这种情况下与double[]不直接兼容
  2. 不能直接通过实例调用sort方法

解决此问题的最少更改是使方法通用,并调用Merge.sort 而不是ms.sort

这是我将如何实现sort

public static void sort<T>(T[] a)
    where T : IComparable<T>
{
    sort(a, 0, a.Length);
}

public static void sort<T>(T[] a, int low, int high)
    where T : IComparable<T>
{
    int N = high - low;
    if (N <= 1)
        return;

    int mid = low + N / 2;

    sort(a, low, mid);
    sort(a, mid, high);

    T[] aux = new T[N];
    int i = low, j = mid;
    for (int k = 0; k < N; k++)
    {
        if (i == mid) aux[k] = a[j++];
        else if (j == high) aux[k] = a[i++];
        else if (a[j].CompareTo(a[i]) < 0) aux[k] = a[j++];
        else aux[k] = a[i++];
    }

    for (int k = 0; k < N; k++)
    {
        a[low + k] = aux[k];
    }
}

请注意,我改为使用T 而不是IComparable,并添加了一个约束,说明我们需要一个实现IComparable&lt;T&gt;T

另外,改变你的电话:

ms.sort(...);

到这里:

Merge.sort(...);

【讨论】:

    【解决方案2】:
        //merge sort recurcive
    
        public void MergeSort(int[] input,int startIndex,int endIndex)
        {
            int mid;
    
            if (endIndex > startIndex)
            {
                mid = (endIndex + startIndex) / 2;
                MergeSort(input, startIndex, mid);
                MergeSort(input, (mid + 1), endIndex);
                Merge(input, startIndex, (mid + 1), endIndex);
            }
        }
    
        public void Merge(int[] input, int left, int mid, int right)
        {
            //Merge procedure takes theta(n) time
            int[] temp = new int[input.Length];
            int i, leftEnd,lengthOfInput,tmpPos;
            leftEnd = mid - 1;
            tmpPos = left;
            lengthOfInput = right - left + 1;
    
            //selecting smaller element from left sorted array or right sorted array and placing them in temp array.
            while ((left <= leftEnd) && (mid <= right))
            {
                if (input[left] <= input[mid])
                {
                    temp[tmpPos++] = input[left++];
                }
                else
                { 
                    temp[tmpPos++]=input[mid++];
                }
            }
            //placing remaining element in temp from left sorted array
            while (left <= leftEnd)
            {
                temp[tmpPos++] = input[left++];
            }
    
            //placing remaining element in temp from right sorted array
            while (mid <= right)
            {
                temp[tmpPos++] = input[mid++];
            }
    
            //placing temp array to input
            for (i = 0; i < lengthOfInput;i++ )
            {
                input[right]=temp[right];
                right--;
            }
        }
    
         int[] input3 = { 22, 4, 6, 0, 9, 12, 156, 86,99};
         MergeSort(input3, 0, input3.Length - 1);
            for (int i = 0; i < input3.Length; i++)
                Console.Write(input3[i]+", ");
            Console.WriteLine("");
    

    【讨论】:

    • 感谢您评论代码。更容易理解。
    【解决方案3】:

    你的sort 方法是静态的,你不应该从你的类的实例中调用它。

    你应该这样称呼它:

    Merge.sort(MyArray);
    

    不是:

    ms.sort(MyArray);
    

    事实上,由于您的Merge 类没有实例方法,因此创建它的实例是没有意义的,您可能应该将整个类标记为静态。

    【讨论】:

    • @HamedKamrava:见@LasseVKarlsen 的回答。您还有另一个问题,double[] 无法自动转换为IComparable[]
    【解决方案4】:

    一个简单的 C# 代码来做归并排序

    using System;
    
    namespace MergeSort
    {
        class Program
        {
            static void Main(string[] args)
            {            
                int[] arInt = { 6, 4, 2, 8, 4, 8, 11, 1, 7, 4, 13, 5, 45, -1, 0, -7, 56, 10, 57 };
                var sortedIntAr = GenericMergeSort<int>.Sort(arInt);
    
                string[] arStr = { "Here", "Is", "A", "Cat", "Really", "Fast", "And", "Clever" };
                var sortedStrAr = GenericMergeSort<string>.Sort(arStr);
    
                Console.WriteLine(String.Join(',', sortedIntAr));
                Console.WriteLine(String.Join(',', sortedStrAr));
    
                Console.ReadLine();
            }
    
        }
        class GenericMergeSort<T> where T : IComparable
        {
            public static T[] Sort(T[] ar)
            {
                var arLen = ar.Length;
                if (arLen < 2)
                    return ar;
    
                var arL = ar.AsSpan(0..(arLen / 2)).ToArray();
                var arR = ar.AsSpan((arLen / 2)..arLen).ToArray();
    
                arL = Sort(arL);
                arR = Sort(arR);
    
                return Merge(arL, arR);
            }
    
            private static T[] Merge(T[] arL, T[] arR)
            {
                var mergedArray = new T[arL.Length + arR.Length];
                int iM = 0, iL = 0, iR = 0;
    
                while (iL < arL.Length || iR < arR.Length)
                {
                    mergedArray[iM++] = iL < arL.Length && (iR > arR.Length - 1 || arL[iL].CompareTo(arR[iR]) < 0)
                                        ? arL[iL++] : arR[iR++];
                }
                return mergedArray;
            }
        }
    }
    

    这是输出

    -7,-1,0,1,2,4,4,4,5,6,7,8,8,10,11,13,45,56,57

    A,And,Cat​​,聪明,快速,Here,Is,Really

    【讨论】:

      【解决方案5】:
      public static int[] mergeSort(int[] ar)
      {
          Func<int[], int[]> firstHalf = (array) =>
           {
               return array.Take((array.Length + 1) / 2).ToArray();
           };
      
          Func<int[], int[]> secondHalf = (array) =>
          {
              return array.Skip((array.Length + 1) / 2).ToArray();                
          };
      
          Func<int[], int[], int[]> mergeSortedArrays = (ar1, ar2) =>
          {
              int[] mergedArray = new int[ar1.Length + ar2.Length];
      
              int i1 = 0, i2 = 0, currentMin;
      
              while (i1 < ar1.Length || i2 < ar2.Length)
              {
                  if (i1 < ar1.Length && i2 < ar2.Length)
                  {
                      if (ar1[i1] < ar2[i2])
                      {
                          currentMin = ar1[i1];
                          i1++;
                      }
                      else
                      {
                          currentMin = ar2[i2];
                          i2++;
                      }
                  }
                  else if (i1 < ar1.Length)
                  {
                      currentMin = ar1[i1];
                      i1++;
                  }
                  else
                  {
                      currentMin = ar2[i2];
                      i2++;
                  }
                  mergedArray[i1 + i2 - 1] = currentMin;
              }
              return mergedArray;
          };
      
          int[] half1 = firstHalf(ar); //always /geq than half2
          int[] half2 = secondHalf(ar);
      
          if (half1.Length < 2)
              return mergeSortedArrays(half1, half2);
          else
              return mergeSortedArrays(mergeSort(half1), mergeSort(half2));
      
      }
      

      【讨论】:

        【解决方案6】:

        一个简单的 C# 归并排序。

        using System.Collections.Generic;
        
        namespace Sort
        {
            public class MergeSort
            {
                public static List<int> mergeSort(List<int> list)
                {
                    if (list.Count <= 1) return list;
        
                    List<int> result;
                    List<int> left = new List<int>();
                    List<int> right = new List<int>();
        
                    int midPoint = list.Count / 2;
        
                    left.AddRange(list.GetRange(0, midPoint));
                    right.AddRange(list.GetRange(midPoint, list.Count - midPoint));
        
                    left = mergeSort(left);
        
                    right = mergeSort(right);
        
                    result = merge(left, right);
                    return result;
                }
        
                //This method will be responsible for combining our two sorted arrays into one giant array
                public static List<int> merge(List<int> left, List<int> right)
                {
                    List<int> result = new List<int>();
        
                    int indexLeft = 0, indexRight = 0, indexResult = 0;
                    while (indexLeft < left.Count || indexRight < right.Count)
                    {
                        //if both arrays have elements  
                        if (indexLeft < left.Count && indexRight < right.Count)
                        {
                            if (left[indexLeft] <= right[indexRight])
                            {
                                result.Add(left[indexLeft]);
                                indexLeft++;
                            }
                            else
                            {
                                result.Add(right[indexRight]);
                                indexRight++;
                            }
                        }
                        else if (indexLeft < left.Count)
                        {
                            result.Add(left[indexLeft]);
                            indexLeft++;
                        }
                        else if (indexRight < right.Count)
                        {
                            result.Add(right[indexRight]);
                            indexRight++;
                        }
                        indexResult++;
                    }
                    return result;
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2021-08-24
          • 1970-01-01
          • 2013-08-04
          • 1970-01-01
          • 2020-09-17
          • 2015-09-23
          • 2021-06-27
          • 2017-04-07
          相关资源
          最近更新 更多