C# 归并排序

发布于:2024-07-30 ⋅ 阅读:(114) ⋅ 点赞:(0)

栏目总目录


概念

归并排序是一种分而治之的排序算法。它将一个大数组分成两个小数组,递归地对这两个小数组进行排序,然后将排序好的小数组合并成一个有序的大数组。这个过程一直递归进行,直到数组被拆分成只有一个元素的数组(自然是有序的),然后开始合并过程,直至合并成完全有序的数组。

原理

归并排序的主要原理是分治法(Divide and Conquer):

  1. 分解:将数组分解成两个较小的子数组,直到子数组的大小为1。
  2. 递归求解:递归地对子数组进行排序。
  3. 合并:将已排序的子数组合并成一个大的有序数组。

合并过程中,通常使用两个指针分别指向两个子数组的起始位置,比较两个指针所指向的元素,将较小的元素放入临时数组中,并移动该指针。当某个子数组的所有元素都被复制后,将另一个子数组中剩余的元素直接复制到临时数组的末尾。最后,将临时数组的内容复制回原数组,完成合并。

好处与不足

好处

  • 稳定性:归并排序是一种稳定的排序算法。
  • 时间复杂度:归并排序的时间复杂度为O(n log n),在平均、最好和最差情况下都是一致的。
  • 分而治之:易于并行实现,适合在并行计算环境中使用。

不足

  • 空间复杂度:归并排序需要额外的空间来存储临时数组,空间复杂度为O(n)。
  • 自顶向下:归并排序是自顶向下的递归算法,对于非常大的数据集,可能会因为递归深度过大而导致栈溢出。

应用场景

  • 适用于大数据量的排序,尤其是在并行计算环境中。
  • 需要稳定性排序的场合,如归并排序可以很好地保持相等元素的原始顺序。
  • 外部排序中,归并排序是常用的算法之一,因为它可以有效地处理存储在外部存储设备(如硬盘)上的大量数据。

示例代码

class MergeSort
{
    // 合并两个已排序的数组段
    private static void Merge(int[] arr, int left, int mid, int right)
    {
        int n1 = mid - left + 1;
        int n2 = right - mid;
        
        // 创建临时数组
        int[] L = new int[n1];
        int[] R = new int[n2];

        // 拷贝数据到临时数组
        for (int i = 0; i < n1; i++)
            L[i] = arr[left + i];
        for (int j = 0; j < n2; j++)
            R[j] = arr[mid + 1 + j];

        // 合并临时数组回到原数组arr[l..r]
        int i = 0, j = 0;
        int k = left;
        while (i < n1 && j < n2)
        {
            if (L[i] <= R[j])
            {
                arr[k] = L[i];
                i++;
            }
            else
            {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        // 拷贝L[]的剩余元素
        while (i < n1)
        {
            arr[k] = L[i];
            i++;
            k++;
        }

        // 拷贝R[]的剩余元素
        while (j < n2)
        {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    // 主函数来排序arr[l..r]
    public static void Sort(int[] arr, int left, int right)
    {
        if (left < right)
        {
            // 同(l+r)/2,但是防止了大数的溢出
            int mid = left + (right - left) / 2;

            // 分别对左右子数组进行排序
            Sort(arr, left, mid);
            Sort(arr, mid + 1, right);

            // 合并结果
            Merge(arr, left, mid, right);
        }
    }

网站公告

今日签到

点亮在社区的每一天
去签到