【问题标题】:MergeSort Implementation in C#C# 中的合并排序实现
【发布时间】:2013-12-26 10:20:34
【问题描述】:

目前正在研究算法分析,而不是盲目地使用我教科书中的伪代码,我正在用 C# 实现每个算法。这是伪代码:

MERGE-SORT(A,p,r)
1  if p < r
2     q = (p+r)/2
3     MERGE-SORT(A,p,q)
4     MERGE-SORT(A,q+1,r)
5     MERGE(A,p,q,r)

MERGE(A,p,q,r)
1  n1 = q - p + 1
2  n2 = r - q
3  let L[1..n1+1] and R[1..n2+1] be new arrays
4  for i = 1 to n1
5     L[i] = A[p+i-1]
6  for j = 1 to n2
7     R[j] = A[q+j]
8  L[n1+1] = INF
9  R[n1+1] = INF
10 i = 1
11 j = 1
12 for k = p to r
13    if L[i] <= R[j]
14       A[k] = L[i]
15       i = i + 1
16    else
17       A[k] = R[j]
18       j = j + 1

这是我的代码:

static void Main(string[] args)
{
    int[] unsortedArray = new int[] { 5, 2, 7, 4, 1, 6, 8, 3, 9, 10 };
    MergeSort(ref unsortedArray, 1, unsortedArray.Length);
    foreach (int element in unsortedArray)
    {
        Console.WriteLine(element);
    }
    Console.Read();
}

private static void MergeSort(ref int[] unsortedArray, int leftIndex, int rightIndex)
{
    if (leftIndex < rightIndex)
    {
        int middleIndex = (leftIndex + rightIndex) / 2;
        //Sort left (will call Merge to produce a fully sorted left array)
        MergeSort(ref unsortedArray, leftIndex, middleIndex);
        //Sort right (will call Merge to produce a fully sorted right array)
        MergeSort(ref unsortedArray, middleIndex + 1, rightIndex);
        //Merge the sorted left & right to finish off.
        Merge(ref unsortedArray, leftIndex, middleIndex, rightIndex);
    }
}

private static void Merge(ref int[] unsortedArray, int leftIndex, int middleIndex, int rightIndex)
{
    int lengthLeft = middleIndex - leftIndex + 1;
    int lengthRight = rightIndex - middleIndex;
    int[] leftArray = new int[lengthLeft + 1];
    int[] rightArray = new int[lengthRight + 1];
    for (int i = 0; i < lengthLeft; i++)
    {
        leftArray[i] = unsortedArray[leftIndex + i - 1];
    }
    for (int j = 0; j < lengthRight; j++)
    {
        rightArray[j] = unsortedArray[middleIndex + j];
    }
    leftArray[lengthLeft] = Int32.MaxValue;
    rightArray[lengthRight] = Int32.MaxValue;
    int iIndex = 0;
    int jIndex = 0;
    for (int k = leftIndex; k < rightIndex; k++)
    {
        if (leftArray[iIndex] <= rightArray[jIndex])
        {
            unsortedArray[k] = leftArray[iIndex];
            iIndex++;
        }
        else
        {
            unsortedArray[k] = rightArray[jIndex];
            jIndex++;
        }
    }
}

我不确定我在哪里搞砸了——我尽可能地遵循伪代码,但我的输出很时髦(即重复的值并且没有正确排序)。

对此进行调试也没有帮助我找出问题所在(递归解决方案太混乱了)。

我哪里出错了,我该如何解决?

【问题讨论】:

  • 记住 C# 的索引是从 0 开始的(从 0 开始,而不是 1)。

标签: c# sorting console-application mergesort


【解决方案1】:

正如 cmets 中正确指出的那样,C# 数组索引是从零开始的,而您的伪代码是从一开始的。

话虽如此,错误如下:

1) 主要方法

MergeSort(ref unsortedArray, 1, unsortedArray.Length);

必须改为:

MergeSort(ref unsortedArray, 0, unsortedArray.Length - 1);

2) 合并方法

leftArray[i] = unsortedArray[leftIndex + i - 1];

必须改为:

leftArray[i] = unsortedArray[leftIndex + i];

3) 合并方法

rightArray[j] = unsortedArray[middleIndex + j];

必须改为:

rightArray[j] = unsortedArray[middleIndex + j + 1];

4) 合并方法

for (int k = leftIndex; k < rightIndex; k++)

必须改为:

for (int k = leftIndex; k <= rightIndex; k++)

顺便说一句,您的代码中的 ref 关键字并不是必需的,因为您只是在修改数组中的值而不是创建它的新实例。

【讨论】:

    【解决方案2】:
    private static void Merge(int[]A, int[]aux, int lo, int mid, int hi)
    {
        for (int k = lo; k <= hi; k++)
            aux[k] = A[k];
    
    
        int i = lo, j = mid + 1;
        for (int k = lo; k <= hi; k++)
        {
            if      (i > mid)           A[k] = aux[j++];
            else if (j > hi)            A[k] = aux[i++];
            else if (aux[j] < aux[i])   A[k] = aux[j++];
            else                        A[k] = aux[i++];
        }
    }
    
    private static void Sort(int[] A, int[] aux, int lo, int hi)
    {
        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;
        Sort(A, aux, lo, mid);
        Sort(A, aux, mid + 1, hi);
        if (A[mid + 1] > A[mid]) return;
        Merge(A, aux, lo, mid, hi);
    }
    
    public static void Sort(int[] A)
    {
        int[] aux = new int[A.Length];
        Sort(A, aux, 0, A.Length - 1);
    }
    

    【讨论】:

      【解决方案3】:

      一个简单的合并排序实现。

      https://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/MergeSort.cs

      using System;
      using System.Collections.Generic;
      using System.Linq;
      
      namespace AlgorithmsMadeEasy
      {
          class MergeSort
          {
              public void MergeSortMethod()
              {
                  var input = System.Console.ReadLine();
                  string[] sInput = input.Split(' ');
                  int[] numbers = Array.ConvertAll(sInput, int.Parse);
                  int len = numbers.Length;
                  MergeSort_Recursive(numbers, 0, len - 1);
                  for (int i = 0; i < len; i++)
                  {
                      Console.Write(numbers[i] + " ");
                  }
      
                  Console.ReadLine();
              }
      
              static public void MergeSort_Recursive(int[] numbers, int left, int right)
              {
                  int mid;
      
                  if (right > left)
                  {
                      mid = (right + left) / 2;
                      MergeSort_Recursive(numbers, left, mid);
                      MergeSort_Recursive(numbers, (mid + 1), right);
      
                      DoMerge(numbers, left, (mid + 1), right);
                  }
              }
      
              static public void DoMerge(int[] numbers, int left, int mid, int right)
              {
                  int[] temp = new int[numbers.Length];
                  int i, left_end, num_elements, tmp_pos;
      
                  left_end = (mid - 1);
                  tmp_pos = left;
                  num_elements = (right - left + 1);
      
                  while ((left <= left_end) && (mid <= right))
                  {
                      if (numbers[left] <= numbers[mid])
                          temp[tmp_pos++] = numbers[left++];
                      else
                          temp[tmp_pos++] = numbers[mid++];
                  }
      
                  while (left <= left_end)
                      temp[tmp_pos++] = numbers[left++];
      
                  while (mid <= right)
                      temp[tmp_pos++] = numbers[mid++];
      
                  for (i = 0; i < num_elements; i++)
                  {
                      numbers[right] = temp[right];
                      right--;
                  }
              }
          }
      }
      
      /*
      Sample Input:
      6 5 3 2 8
      
      Calling Code:
      MergeSort ms = new MergeSort();
      ms.MergeSortMethod();
      */
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-31
        • 2022-01-03
        相关资源
        最近更新 更多