简体   繁体   English

C#中的MergeSort实现

[英]MergeSort Implementation in C#

Currently studying algorithm analysis, and instead of blindly running off of pseudo-code from my textbook, I'm implementing each algorithm in C#.目前正在研究算法分析,而不是盲目地从我的教科书中跑掉伪代码,我正在用 C# 实现每个算法。 This is the psuedo-code:这是伪代码:

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

This is my code:这是我的代码:

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++;
        }
    }
}

I'm not sure where I'm messing things up -- I tried to follow the pseudo-code as well as I could, but my output is funky (ie repeated values and not properly sorted).我不确定我在哪里搞砸了 - 我试图尽可能地遵循伪代码,但我的输出很时髦(即重复的值并且没有正确排序)。

Debugging this didn't help me figure out the problem either (recursive solutions get too messy).调试这个也没有帮助我找出问题(递归解决方案变得太混乱了)。

Where am I going wrong, and how do I fix it?我哪里出错了,我该如何解决?

As correctly pointed out in the comments, C# array indexing is zero-based, while your pseudo code is one-based.正如评论中正确指出的那样,C# 数组索引是从零开始的,而您的伪代码是从一开始的。

That being said, here's the errors:话虽如此,这里是错误:

1) Main method 1) 主要方法

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

has to be changed to:必须改为:

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

2) Merge method 2)合并方法

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

has to be change to:必须改为:

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

3) Merge method 3) 合并方法

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

has to be change to:必须改为:

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

4) Merge method 4) 合并方法

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

has to be change to:必须改为:

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

BTW, the ref keyword in your code is not really necessay, since you're just modifying the values inside the array and not creating a new instance of it .顺便说一句,代码中的ref关键字并不是必需的,因为您只是修改数组中的值而不是创建它的新实例。

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

A Simple Merge Sort Implementation.一个简单的归并排序实现。

https://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/MergeSort.cs 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();
*/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM