分治与递归----归并排序

本文介绍了一种基于分治递归思想的有效稳定排序方法——归并排序。它通过将待排序集合不断拆分为更小的子集,分别排序后再合并的方式实现整体排序。归并排序的时间复杂度为O(nlogn),适用于多种输入数据情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       归并排序是采用分治递归的思想来实现的,是一种有效的稳定的排序,其一般复杂度在O(nlogn)。

       基本思想:将待排序的元素进行分组,将原来一个大的集合分成两个小的集合(这里就要采用分治递归的思想,子问题是独立的),再对小的集合进行排序,最终将已经排序好的小的集合进行合并,从而组成要求的排好序的集合。

void mergerarry(int *a, int x, int mid, int y, int *t)//x代表此时集合的首元素的位置,y代表此时集合的末元素的位置
{
    int m = mid, n = y;
    int i = x, j = mid + 1;
    int k = 0;
    while(i <= m && j <= n)//判读哪个子集的首元素比较小,放入t中,直到一个集合为空
    {
        if(a[i] <= a[j])
            t[k++] = a[i++];
        else
            t[k++] = a[j++];
    }
    
    //如果其中一个集合非空,则要将剩余的元素放入t中,此时非空集合的首元素肯定会比放进去的大
    while(i <= m)
        t[k++] = a[i++];
    while(j <= n)
        t[k++] = a[j++];
    for(i = 0; i < k; i++)//经t中排好序的元素重新输入a中,保证接下来的更大一点的子集的排序
        a[x + i] = t[i];
    return ;
}
void merger_sort(int *a, int x, int y, int *t)
{
    if(y > x)
    {
        int mid = (x + y) / 2;
        //采用二分的思想
        merger_sort(a, x, mid, t);
        merger_sort(a, mid + 1, y, t);
        mergerarry(a, x, mid, y, t);
    }
    return ;
}
       归并排序的好处就在与其不依赖于输入数组中元素的组合方式,避免了快速排序的中最糟糕的情况,当然,在一些情况下,归并排序不比快速排序更快,归并排序要是用额外的数组来帮助,付出了一些空间代价,可以算是归并排序的缺点。
分治算法是一种将复杂问题分解成较小的、相似的子问题,并递归地解决这些子问题,最后合并结果来得到原问题解的策略。在排序算法中,归并排序就是一种经典的分治策略应用实例。 归并排序的核心思想是“分”和“合”。它首先将数组分为两个长度相等的子数组(如果数组长度不是偶数,则会有一个较短的子数组),然后对每个子数组进行排序,接着合并这两个已排序的子数组。这个过程一直递归下去,直到子数组只剩下一个元素,此时视为已排序。合并操作是通过比较两个子数组的首元素,将较小的放入结果数组,然后移动指针继续比较,直至完成。 在C++中,你可以使用递归来实现归并排序。下面是一个简单的示例: ```cpp void mergeSort(int arr[], int left, int right) { if (left < right) { int mid = left + (right - left) / 2; mergeSort(arr, left, mid); mergeSort(arr, mid + 1, right); merge(arr, left, mid, right); } } void merge(int arr[], int left, int mid, int right) { int n1 = mid - left + 1; int n2 = right - mid; // 创建临时数组 int L[n1], R[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]; // 合并临时数组回原数组 int i = 0, j = 0, k = left; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } // 处理剩余部分 while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值