c++ 深入理解归并排序的用法

C++深入理解归并排序的用法

什么是归并排序

归并排序是一种经典的分治算法,它将一个大问题分解成小问题来解决。通过不断将两个已排好序的子序列合并成一个更大的已排好序的序列,最终达到整个序列有序的目的。由于采用了分治思想,时间复杂度为 O(NlogN),是一种比较高效的排序算法。

归并排序的实现

关键思想

归并排序的核心思想是分治。我们将待排序的序列分成两半,分别对两半进行排序,然后将排好序的两半合并成一个有序序列。

实现步骤

  1. 递归分解待排序数组

  2. 合并两个有序数组

代码实现

以下为归并排序的C++代码实现:

void mergesort(vector<int>& nums, int start, int end){
    if(start >= end) return;
    int mid = start + (end-start)/2;
    mergesort(nums, start, mid);
    mergesort(nums, mid+1, end);
    merge(nums, start, mid, end);
}

void merge(vector<int>& nums, int start, int mid, int end){
    vector<int> tmp(end-start+1);
    int i = start, j = mid+1, k = 0;
    while(i <= mid && j <= end){
        if(nums[i] < nums[j]){
            tmp[k++] = nums[i++];
        }else{
            tmp[k++] = nums[j++];
        }
    }
    while(i <= mid){
        tmp[k++] = nums[i++];
    }
    while(j <= end){
        tmp[k++] = nums[j++];
    }
    for(int i = start; i <= end; i++){
        nums[i] = tmp[i-start];
    }
}

使用归并排序解决问题

归并排序的应用非常广泛,例如:

问题1:求逆序对数量

逆序对指的是在一个序列中,左边的数大于右边的数的数对数量。归并排序可以通过在合并两个有序数组的时候,统计逆序对数量来解决这个问题。

以下为求逆序对数量的C++代码实现:

int count_inversion(vector<int>& nums, int start, int end){
    if(start >= end) return 0;
    int mid = start + (end-start)/2;
    int left = count_inversion(nums, start, mid);
    int right = count_inversion(nums, mid+1, end);
    int cnt = 0, i = start, j = mid+1;
    vector<int> tmp(end-start+1);
    int k = 0;
    while(i <= mid && j <= end){
        if(nums[i] <= nums[j]){
            tmp[k++] = nums[i++];
        }else{
            tmp[k++] = nums[j++];
            cnt += mid-i+1;
        }
    }
    while(i <= mid){
        tmp[k++] = nums[i++];
    }
    while(j <= end){
        tmp[k++] = nums[j++];
    }
    for(int i = start; i <= end; i++){
        nums[i] = tmp[i-start];
    }
    return cnt+left+right;
}

问题2:求逆序对数量

归并排序还可以用来对链表进行排序,特别是当链表很长时,归并排序比快速排序更稳定、效率更高。

以下为链表排序的C++代码实现:

ListNode* mergeSort(ListNode* head){
    if(head == NULL || head->next == NULL){
        return head;
    }
    ListNode* fast = head->next;
    ListNode* slow = head;
    while(fast && fast->next){
        slow = slow->next;
        fast = fast->next->next;
    }
    ListNode* mid = slow->next;
    slow->next = NULL;
    ListNode* left = mergeSort(head);
    ListNode* right = mergeSort(mid);
    return merge(left, right);
}

ListNode* merge(ListNode* l, ListNode* r){
    if(l == NULL) return r;
    if(r == NULL) return l;
    if(l->val < r->val){
        l->next = merge(l->next, r);
        return l;
    }else{
        r->next = merge(l, r->next);
        return r;
    }
}

结语

归并排序是一种非常实用的排序算法,代码实现不难,但理解其原理则需要更深刻的思考。在实际编程时,我们可以借助冒泡和快速排序的思想,来更好地理解归并排序。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++ 深入理解归并排序的用法 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Go并发编程实现数据竞争

    Go并发编程实现数据竞争攻略 在Go语言中,实现并发编程时需要注意数据竞争的问题。数据竞争指的是多个goroutine同时访问和修改共享的数据,而没有进行同步操作,导致结果的不确定性和错误。下面是一些实现并发编程时避免数据竞争的攻略。 1. 使用互斥锁 互斥锁是一种常用的同步机制,用于保护共享资源的访问。在Go语言中,可以使用sync包提供的Mutex类型来…

    other 2023年7月29日
    00
  • 魔兽世界战士属性优先级 6.0战士如何堆属性

    魔兽世界(WOW)的战士职业是一个十分强力的近战攻击职业,战士在不同的专精及副本进度下,优先堆放的属性也会有所不同。以下是详细的优先级攻略。 1.战士属性优先级 战士的属性优先级取决于职业专精及当前的副本进度,但总体来说,优先级排序如下: 爆击率(Critical Strike) 全能(Mastery) 狂怒( Haste) 急速( Versatility)…

    other 2023年6月27日
    00
  • C语言深入讲解内存操作问题

    C语言深入讲解内存操作问题 介绍 在C语言中,内存操作是非常重要的一部分。了解如何正确地操作内存可以帮助我们编写高效、可靠的程序。本攻略将详细讲解C语言中的内存操作问题,包括内存分配、指针操作和内存泄漏等。 内存分配 在C语言中,我们可以使用malloc函数来动态分配内存。malloc函数接受一个参数,即所需内存的大小(以字节为单位),并返回一个指向分配内存…

    other 2023年8月1日
    00
  • 说不尽的MVVM(2) – MVVM初体验

    在MVVM架构中,ViewModel是连接View和Model的桥梁,负责处理View的业务逻辑和数据展示,同时也负责与Model层进行数据交互。在本文中,我们将介绍MVVM架构中的ViewModel层,以及如何使用ViewModel实现数据绑定和业务逻辑处理。 1. ViewModel的作用 在MVVM架构中,ViewModel层是连接View和Model…

    other 2023年5月5日
    00
  • Flutter实现下拉刷新和上拉加载更多

    下面是针对“Flutter实现下拉刷新和上拉加载更多”的完整攻略: Flutter实现下拉刷新和上拉加载更多 1. 简介 下拉刷新和上拉加载更多是移动端APP开发中常用的功能,它们可以提高用户体验和应用的交互性。Flutter框架提供了很多开箱即用的控件来帮助我们实现这些功能。本篇文章将介绍如何使用Flutter框架实现下拉刷新和上拉加载更多。 2. 下拉刷…

    other 2023年6月25日
    00
  • Win11右键菜单没反应怎么办 Win11鼠标右键不能用修复教程

    如果 Win11 右键菜单没有反应,主要原因是由于系统配置问题或者某些软件冲突引起。下面是修复 Win11 右键菜单无法使用的几种方法。 方法一:检查鼠标设置 在 Win11 中,鼠标右键菜单无法使用,首先要检查鼠标的设置是否正确。可以按下 Win + I 组合键打开“设置”窗口,选择“设备” -> “鼠标”选项来检查鼠标设置。 如果发现鼠标设置异常或…

    other 2023年6月27日
    00
  • 什么是rest接口?

    REST是一种Web服务架构风格,它支持客户端-服务端的通信模式,在网络上交换数据。RESTful接口是基于HTTP协议的一种API,是一种通过 HTTP 进行通信的Web应用程序接口。 RESTful接口设计遵循HTTP协议的规范,使用HTTP请求方式定义对资源的操作,也就是使用HTTP的GET、POST、PUT、DELETE等请求方式去对资源进行CRUD…

    其他 2023年4月16日
    00
  • 小米无法开机怎么办?小米手机强制重启教程

    小米无法开机怎么办?小米手机强制重启教程 如果你的小米手机无法开机,或者开机后卡在启动界面上,无法进入系统,那么可以尝试通过强制重启的方法来解决问题。 强制重启方法 强制重启的方法因不同小米手机型号而异,以下将具体介绍: 小米8系列、小米MIX2S、小米5s、小米5s Plus、小米5X、小米Max2、小米Note3、小米MIX、小米5c、小米4S、小米4c…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部