【问题标题】:Merge Sorting a String Array in C#在 C# 中合并排序字符串数组
【发布时间】:2017-09-22 23:45:24
【问题描述】:

我正在尝试编写一个数组排序和搜索程序,该程序将处理字符串数组中的 600 个项目。要排序的数据如下所示:

2017 | 25 |一月 | 9994750 | 27.640 | 36.800 |希腊多德卡尼斯群岛 | 1485307173 | 01:19:33 | 4.000 |

我一直在尝试实现合并排序来对这些数据进行排序。但是,我无法弄清楚如何将一个为 int 数组设计的合并排序程序转换为一个为对字符串数组进行排序的程序。谁能解释一下我是怎么做到的?

虽然这可以通过使用现有的内置函数来完成,但我一直在尝试这样做,为明年的大学课程做准备,因此我不得不从头开始编写 Merge 排序而不使用内置函数。

旁注:我必须注意,我知道在当前形式下,即使使用合并排序,程序也无法自然地对月份进行排序,但这是我已经有一个工作回合,一旦我可以让合并排序运行为有意的。

当前的归并排序程序:

        static public void MainMerge(string[] numbers, int left, int mid, int right)
    {
        int[] temp = new int[25];
        int i, eol, num, pos;

        eol = (mid - 1);
        pos = left;
        num = (right - left + 1);

        while ((left <= eol) && (mid <= right))
        {
            if (numbers[left].CompareTo(numbers[mid]))
                temp[pos++] = numbers[left++];
            else
                temp[pos++] = numbers[mid++];
        }

        while (left <= eol)
            temp[pos++] = numbers[left++];

        while (mid <= right)
            temp[pos++] = numbers[mid++];

        for (i = 0; i < num; i++)
        {
            numbers[right] = temp[right];
            right--;
        }
    }

    static public void SortMerge(string[] numbers, int left, int right)
    {
        int mid;

        if (right > left)
        {
            mid = (right + left) / 2;
            SortMerge(numbers, left, mid);
            SortMerge(numbers, (mid + 1), right);

            MainMerge(numbers, left, (mid + 1), right);
        }
    }

【问题讨论】:

  • 尝试重新利用代码通常比它的价值更多。这似乎是一项非常简单的任务,最好从头开始。
  • @coinbird 什么?这使用泛型非常简单。没有理由“从头开始”
  • 您应该使用实现 IComparable 的泛型来实现排序。 public void MergeSort&lt;T&gt;(this T[] elements) where T : IComparable { }
  • 有什么理由不能使用Array.Sort(array); 而不是实现自己的排序?
  • @GiggyLapisar 在编码方面的进步意味着你正在学习以正确的方式做事。在这里使用泛型是正确的方法。复制您的代码并将string 替换为int 会起作用,但这是一个糟糕的解决方案。

标签: c# arrays sorting merge mergesort


【解决方案1】:

为了让您的算法能够在不同类型上运行,我们使用 C# 泛型。我对您的代码进行了以下更改:

  • numbers 参数重命名为values,以更好地适应其他更改
  • 将数组的数据类型从string更改为T
  • 添加了类型约束,因此T 需要与其他T 具有可比性
  • 也将temp 数组的类型更改为T
  • 您已经在使用CompareTo 进行比较,因此不需要更改其他代码编辑:实际上,IComparable.CompareTo 的返回值与string.CompareTo 不同,因此需要稍作调整制作

我使用了IComparable&lt;T&gt; 而不是IComparable。两者都应该同样适用于您的目的。

代码如下:

static public void MainMerge<T>(T[] values, int left, int mid, int right) where T : IComparable<T>
{
    T[] temp = new T[25];
    int i, eol, num, pos;

    eol = (mid - 1);
    pos = left;
    num = (right - left + 1);

    while ((left <= eol) && (mid <= right))
    {
        if (values[left].CompareTo(values[mid]))
            temp[pos++] = values[left++];
        else
            temp[pos++] = values[mid++];
    }

    while (left <= eol)
        temp[pos++] = values[left++];

    while (mid <= right)
        temp[pos++] = values[mid++];

    for (i = 0; i < num; i++)
    {
        values[right] = temp[right];
        right--;
    }
}

static public void SortMerge<T>(T[] values, int left, int right) where T : IComparable<T>
{
    int mid;

    if (right > left)
    {
        mid = (right + left) / 2;
        SortMerge(values, left, mid);
        SortMerge(values, (mid + 1), right);

        MainMerge(values, left, (mid + 1), right);
    }
}

然后,您可以在与其自身可比较的任何类型的数组上调用它。 intstring 应该都可以正常工作。

【讨论】:

  • 似乎应该可以。出于某种原因,尽管 .CompareTo 部分会引发“无法将 int 隐式转换为 bool”错误。
  • @GiggyLapisar 好的,CompareTo 如果项目相等则返回 0,如果左侧项目首先排序,则返回 -1,如果右侧项目首先排序,则返回 1。所以比较合适的整数。我认为您应该将&lt; 0 添加到条件中。抱歉,我没有可用的编辑器。应该是:if (values[left].CompareTo(values[mid]) &lt; 0)我认为
  • @GiggyLapisar 见remarks
  • 是的,效果很好。太感谢了。现在我只需要快速通读一遍就能真正理解它是如何工作的。
猜你喜欢
  • 1970-01-01
  • 2012-11-29
  • 2018-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多