带你深入浅出新面经:十一、十大排序之归并排序

此为面经第十一谈!关注我,每日带你深入浅出一个新面经。

我们要了解面经要如何“说”

很重要!很重要!很重要!

我们通常采取总-分-总方式来阐述!(有些知识点,你可以去了解,但是面经并不是需要全部了解的)

码农不易,各位学者学到东西请点赞支持支持

排序算法部分可以记忆简单过程概述。

开始部分:

总:归并排序是用的是分治、递归思想。将数组分解至单一元素然后再组合成有序的数组。

分:

最好时间复杂度就是(nlogn)(只在外层循环遍历一次就排序完成)

最差时间复杂度就是(nlogn)

平均时间复杂度也是(nlogn)

空间复杂度:n

稳定性:稳定。

归并排序算法实现:

#include <iostream>
#include <vector>

// 合并两个有序数组的函数
void merge(std::vector<int>& arr, int left, int mid, int right) {
    // 计算左子数组和右子数组的大小
    int n1 = mid - left + 1; // 左子数组的大小
    int n2 = right - mid;    // 右子数组的大小

    // 创建临时数组用于存储左子数组和右子数组
    std::vector<int> L(n1); // 临时左子数组
    std::vector<int> R(n2); // 临时右子数组

    // 复制数据到临时左子数组 L
    for (int i = 0; i < n1; i++)
        L[i] = arr[left + i]; // 例如:L = [12, 11, 13],当 left = 0, mid = 2

    // 复制数据到临时右子数组 R
    for (int j = 0; j < n2; j++)
        R[j] = arr[mid + 1 + j]; // 例如:R = [5, 6, 7],当 mid = 2, right = 5

    // 合并临时数组 L 和 R 到原数组 arr
    int i = 0; // 左子数组的初始索引
    int j = 0; // 右子数组的初始索引
    int 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++; // 移动原数组的索引
    }
}

// 递归地分割和排序数组的函数
void mergeSort(std::vector<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 printArray(const std::vector<int>& arr) {
    for (int num : arr) // 遍历数组中的每个元素
        std::cout << num << " "; // 打印元素
    std::cout << std::endl; // 打印换行符
}

// 主函数
int main() {
    // 初始化数组
    std::vector<int> arr = {12, 11, 13, 5, 6, 7};
    std::cout << "Given array is \n";
    printArray(arr); // 打印排序前的数组

    // 调用 mergeSort 函数对数组进行排序
    mergeSort(arr, 0, arr.size() - 1);

    std::cout << "\nSorted array is \n";
    printArray(arr); // 打印排序后的数组
    return 0; // 程序结束
}

归并排序的简单概述过程:

  1. 分解:将数组递归地分成两半,直到每半包含一个元素。
  2. 合并:将两个有序的单元素数组合并成有序的双元素数组。
  3. 递归合并:重复合并过程,逐步合并成更大的有序数组。

总: 排序可视化网站(建议打开看着代码来了解)Comparison Sorting Visualization (usfca.edu)

看着排序过程来理解代码实现会更好。

归并排序的关键在于合并步骤,这一步骤需要仔细地将两个有序子数组合并成一个更大的有序数组。这个过程是递归地进行,直到最终整个数组变得有序。

  学习链接:https://xxetb.xetslk.com/s/3Kif2D

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值