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学习笔记之map的声明和初始化

    下面是关于“Go学习笔记之map的声明和初始化”的详细讲解攻略。 标题 Go学习笔记之map的声明和初始化 简介 Go语言中的map是一种关联数组类型,可以将一个键映射到一个值。在使用map前需要进行声明和初始化操作。本文将详细讲解map的声明和初始化方法。 正文 map的声明 在Go语言中,可以通过make()函数来创建map。语法如下: mapName …

    other 2023年6月20日
    00
  • MySQL验证用户权限的方法

    MySQL验证用户权限的方法首先需要了解MySQL的权限体系及其相关概念: 用户:连接MySQL数据库系统的用户。 主机:连接MySQL数据库系统的客户机所在的主机。 权限:用户对某个主机上某个数据库执行某个操作的权限。 而MySQL权限体系中包含如下权限: ALL PRIVILEGES:所有权限。 CREATE:创建数据库和表。 DROP:删除数据库和表。…

    other 2023年6月27日
    00
  • Android中Glide加载库的图片缓存配置究极指南

    下面将为您详细讲解“Android中Glide加载库的图片缓存配置究极指南”的完整攻略。 一、前言 Glide是一个优秀的Android图片加载库,它能够快速高效地加载图片,并且提供了许多有用的功能,例如内存和磁盘缓存、图片压缩和变换等。但是,如果不配置好它的缓存策略,很容易导致内存溢出或者频繁地从磁盘读取图片,影响应用的性能和用户体验。因此,本文将为大家提…

    other 2023年6月27日
    00
  • 360浏览器如何查看浏览器历史记录 360浏览器屏蔽右键鼠标手势教程

    如何查看浏览器历史记录 通过菜单方式查看历史记录 打开360浏览器 点击浏览器窗口左上角的“三横杠”图标,弹出下拉菜单 在下拉菜单中,选择“历史”,即可查看你当前所用电脑的所有历史记录 点击列表中的条目,即可访问该网页 通过快捷键方式查看历史记录 打开360浏览器 按下键盘上的“Ctrl + H”快捷键,即可弹出历史记录菜单 在弹出的窗口中,选择需要查看的历…

    other 2023年6月27日
    00
  • Mysql存储过程、触发器、事件调度器使用入门指南

    当然!下面是关于\”Mysql存储过程、触发器、事件调度器使用入门指南\”的完整攻略,包含两个示例说明。 … … … … … … … … … … … … … … … … … … … … … … … … … … … … …

    other 2023年8月20日
    00
  • 【Alpha】Scrum Meeting 3

    【Alpha】Scrum Meeting 3 简介 本文是关于Alpha项目的Scrum Meeting 3的记录。 会议时间 2021年8月15日,周日,晚上7点至8点。 参会成员 产品经理:张三 开发者:李四、王五、赵六、钱七 测试人员:小明、小红 议题 1. 任务完成情况 开发者汇报了上一次Sprint期间所完成的任务,并展示了相关的代码和实现情况。测…

    其他 2023年3月28日
    00
  • win10 Build 10108版本来了:开关控件有所变化

    Win10 Build 10108版本来了:开关控件有所变化攻略 1. 简介 Win10 Build 10108版本是Windows 10的一个更新版本,其中的新特性之一是开关控件有所变化。这些变化包括开关控件的颜色和形状等方面的改变。 2. 开关控件颜色变化 在Win10 Build 10108版本中,开关控件的颜色变得更加明亮和鲜艳。这是因为在新版本中,…

    other 2023年6月26日
    00
  • 在Python的Django框架中创建和使用模版

    以下是在Python的Django框架中创建和使用模板的完整攻略: 创建模板文件 在Django项目的根目录下创建一个名为templates的文件夹,用于存放模板文件。 在templates文件夹中创建一个以.html为后缀的模板文件,例如index.html。 编写模板文件 打开index.html文件,使用HTML和Django模板语言编写页面内容。 可…

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