排序算法 C++如何实现归并排序

基本思想

归并排序一般指2-路归并排序。基本思想如下:

第一个问题:
1、假设待排序列由两段有序的左右子序列拼接而成
2、那么只需要一个额外空间当辅助空间,从左段和右段的第1开始比较,小的放到额外空间的低位。一直到两段排完

第二个问题:
1、如何让这两段序列有序?
2、试想如果序列长度为2,那么可看成是左右两段有序子序列。
3、那么只需要将长度为n的看成n个有序的子序列。
4、每个子序列用第一个问题的思想两两拼接成一段长度为2的序列
5、拼接好的序列再一次拼接,直到最后最后排完。

实现

第一个问题的实现:

把两段子序列拼接到vector T,再复制回原来的数组nums
最后两个while是当两段其中一段已全部归并了,而另外一段还没有,
剩下的部分一定是最大的,可以直接将剩余部分复制到 T 对应的位置。
void Merge(vector<int>&nums,unsigned low,unsigned mid,unsigned high){

    unsigned i=low,j=mid+1,k=low;

    while(i<=mid&&j<=high){
        if(nums[i]<=nums[j])
            T[k++]=nums[i++];
        else
            T[k++]=nums[j++];
        }
        while(i<=mid)  T[k++]=nums[i++];
        while(j<=high) T[k++]=nums[j++];
        for(unsigned tn=low; tn<=high;tn++) nums[tn]=T[tn];
}

第二个问题的实现:

将长序列不停划分成两段,直到长度为 1;
函数往回递归,程序回到Merge(nums,low,mid,high)语句将两段
合为一段;
递归到最后则全部序列排序完成。

void Msort(vector<int>& nums,unsigned low ,unsigned high){
        if(low==high) return;
        else{
            unsigned mid = (low+high)/2;
            Msort(nums,low,mid);
            Msort(nums,mid+1,high);
            Merge(nums,low,mid,high);
        }
}

测试:

T为全局的vector

vector<int> vec{7,5,6,4,4,3,2,6,78,45,
				32,0,23,54,2,34,99,55};
    T.resize(vec.size());
    Msort(vec,0,vec.size()-1);
    for(int data : vec)
        cout<<data<<" ";
    cout<<endl;

结果:
在这里插入图片描述

分析:

每次划分成两段,划分log2n次;
两段合并成一段,每次操作不超过n次;
时间复杂度为O(nlog2n);
借助中间数组T长度为n;
空间复杂度为O(n)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
归并排序是一种经典的排序算法,它的实现可以使用C语言。具体步骤如下: 1. 定义一个递归函数mergeSort,用于对待排序的数组进行划分和合并操作。 2. 在mergeSort函数中,判断数组的长度是否大于1,如果不大于1,则直接返回。 3. 如果数组长度大于1,将数组划分为两个子数组,分别递归调用mergeSort函数对这两个子数组进行排序。 4. 接下来,定义一个merge函数,用于将两个已经排序好的子数组合并成一个有序数组。 5. 在merge函数中,使用两个指针分别指向两个子数组的开头,并比较指针所指的元素大小。 6. 将较小的元素放入临时数组中,并将对应的指针向后移动一位。 7. 重复上述步骤,直到其中一个子数组的元素全部放入临时数组中。 8. 将剩余的子数组中的元素依次放入临时数组中。 9. 最后,将临时数组中的元素复制回原数组。 以下是C语言实现归并排序算法的代码: ```c #include <stdio.h> void merge(int arr[], int left[], int leftSize, int right[], int rightSize) { int i = 0, j = 0, k = 0; while (i < leftSize && j < rightSize) { if (left[i] <= right[j]) { arr[k++] = left[i++]; } else { arr[k++] = right[j++]; } } while (i < leftSize) { arr[k++] = left[i++]; } while (j < rightSize) { arr[k++] = right[j++]; } } void mergeSort(int arr[], int size) { if (size <= 1) { return; } int mid = size / 2; int left[mid]; int right[size - mid]; for (int i = 0; i < mid; i++) { left[i] = arr[i]; } for (int i = mid; i < size; i++) { right[i - mid] = arr[i]; } mergeSort(left, mid); mergeSort(right, size - mid); merge(arr, left, mid, right, size - mid); } int main() { int arr[] = {5, 2, 8, 1, 9, 4, 6, 3, 7}; int size = sizeof(arr) / sizeof(arr[0]); mergeSort(arr, size); for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } return 0; } ``` 这段代码可以将数组 {5, 2, 8, 1, 9, 4, 6, 3, 7} 进行归并排序,最终输出排序后的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值