十大排序算法之归并排序

目录

前言

十大排序算法包括哪些

归并排序原理

归并排序基本信息

代码实现

代码思路

递归实现

代码实现

实例

【模板】排序

代码

 总结

基本原理

算法描述

时间复杂度和空间复杂度


前言

排序是重要又较为简单的算法之一,个人认为学习算法建议先学习排序,排序有十种重要的排序方法,有些好,有些坏。

十大排序算法包括哪些

十大排序算法包括冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序。

今天我来讲讲归并排序。

归并排序原理

归并排序的核心在于将一个大的数组不断分成两半,递归地对两半进行排序,最后将排序好的两半合并在一起。具体步骤如下:

  1. 分解‌:将待排序的序列划分为两个子序列,直到子序列的长度为1(此时认为子序列是有序的)。
  2. 递归排序并合并‌:递归地对子序列进行归并排序,并将已排序的子序列合并成一个大的有序序列,直到合并为1个完整的序列。

归并排序基本信息

英文名merge sort‌
时间复杂度O(n log n)
空间复杂度O(n)
是否稳定

代码实现

代码思路

归并排序的代码思路可以分为递归实现和非递归实现两种方式。

递归实现

归并排序的递归实现过程如下:

  1. 分解‌:将数组从中间分成两个子数组,递归地对这两个子数组进行排序。
  2. 合并‌:将排好序的两个子数组合并成一个有序数组。
  3. 终止条件‌:当子数组只有一个元素时,认为该子数组已经有序,递归结束。

代码实现

/*头文件部分*/
#include <iostream>
#include <vector>
/*归并排序部分*/
void merge(std::vector<int>& vec, int left, int mid, int right) {
    std::vector<int> temp(right - left + 1);
    int i = left, j = mid + 1, k = 0;
    while(i <= mid && j <= right)
        temp[k++] = vec[i] <= vec[j] ? vec[i++] : vec[j++];
    while(i <= mid)
        temp[k++] = vec[i++];
    while(j <= right)
        temp[k++] = vec[j++];
    for(k = 0, i = left; i <= right; ++i, ++k)
        vec[i] = temp[k];
}
void mergeSort(std::vector<int>& vec, int left, int right) {
    if(left < right) {
        int mid = left + (right - left) / 2;
        mergeSort(vec, left, mid);
        mergeSort(vec, mid + 1, right);
        merge(vec, left, mid, right);
    }
}
/*主函数部分*/
int main() {
    int n;
    std::cin >> n;
	std::vector<int> vec;
    for (int i = 0; i < n; ++i) {
	    int num;
	    std::cin >> num;
	    vec.push_back(num);
	}
    mergeSort(vec, 0, vec.size() - 1);
    int i = 1;
	for(int num : vec) {
        std::cout << "第" << i << "个数:" << num << std::endl;
        i++;
	}
    return 0;
}

实例

【模板】排序

题目描述

将读入的 N 个数从小到大排序后输出。

输入格式

第一行为一个正整数 N。

第二行包含 N 个空格隔开的正整数 ai,为你需要进行排序的数。

输出格式

将给定的 N 个数从小到大输出,数之间空格隔开,行末换行且无空格。

样例1

样例输入1
5
4 2 4 5 1

样例输出1
1 2 4 4 5

本题来自洛谷题目

​​​​​​P1177 【模板】排序https://www.luogu.com.cn/problem/P1177icon-default.png?t=O83Ahttps://www.luogu.com.cn/problem/P1177

代码

#include <iostream>
#include <vector>
 void merge(std::vector<int>& vec, int left, int mid, int right) {
    std::vector<int> temp(right - left + 1);
    int i = left, j = mid + 1, k = 0;
    while(i <= mid && j <= right)
        temp[k++] = vec[i] <= vec[j] ? vec[i++] : vec[j++];
    while(i <= mid)
        temp[k++] = vec[i++];
    while(j <= right)
        temp[k++] = vec[j++];
    for(k = 0, i = left; i <= right; ++i, ++k)
        vec[i] = temp[k];
}
void mergeSort(std::vector<int>& vec, int left, int right) {
    if(left < right) {
        int mid = left + (right - left) / 2;
        mergeSort(vec, left, mid);
        mergeSort(vec, mid + 1, right);
        merge(vec, left, mid, right);
    }
}
int main() {
    int n;
    std::cin >> n;
	std::vector<int> vec;
    for (int i = 0; i < n; ++i) {
	    int num;
	    std::cin >> num;
	    vec.push_back(num);
	}
    mergeSort(vec, 0, vec.size() - 1);
	for(int num : vec)
        std::cout << num << " ";
    std::cout << std::endl;
    return 0;
}

 总结

归并排序是一种高效的排序算法,基于分治策略,通过递归分解和合并操作实现排序。其核心思想是将一个数组分成若干个子数组,分别对每个子数组进行排序,然后将已排序的子数组合并成一个完整的排序数组。

基本原理

归并排序的基本步骤包括:

  1. 分解‌:将数组从中间分成两半,分别对左半部分和右半部分进行归并排序。
  2. 递归‌:递归地对每一半进行分解,直到每个子数组只有一个元素(自然是有序的)。
  3. 合并‌:将两个有序的子数组合并成一个有序的数组。

算法描述

归并排序的具体算法描述如下:

  1. 分解‌:计算中点 mid = (l + r) / 2
  2. 递归‌:递归调用 mergeSort(a, l, mid) 和 mergeSort(a, mid + 1, r)
  3. 合并‌:将两个有序数组合并成一个有序数组,存储到 a[l:r]
  4. 调用‌:调用 mergeSort(a, 0, n-1) 即可得到整个数组的排序结果。

时间复杂度和空间复杂度

  • 时间复杂度‌:分解步骤的时间复杂度为 O(logn),因为数组被反复分成两半;合并步骤的时间复杂度为 O(n),因为需要遍历两个子数组来合并它们。因此,总的时间复杂度为 O(nlogn)。
  • 空间复杂度‌:合并步骤需要一个额外的数组来存储合并后的结果,所以空间复杂度为 O(n)。

你学费了吗?

下期预告:十大排序算法之计数排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值