首页 > 编程语言 >深入了解归并排序算法

深入了解归并排序算法

时间:2023-09-14 22:33:52浏览次数:32  
标签:归并 int arr 算法 数组 排序 left

归并排序(Merge Sort)是一种高效的、基于分治法的排序算法,它的稳定性和性能使其成为常用的排序方法之一。本文将详细介绍归并排序的工作原理,提供示例和Python、Go、Java以及C语言的实现代码。

归并排序的基本思想

归并排序的核心思想是将数组分成两个子数组,递归地对这两个子数组进行排序,然后将它们合并成一个有序数组。这个过程分为以下几个步骤:

  1. 分割数组: 将待排序的数组分成两个子数组,通常是平均分割。这一步持续递归,直到每个子数组只包含一个元素。
  2. 递归排序: 递归地对左子数组和右子数组进行排序,直到它们都变成有序数组。
  3. 合并数组: 将已排序的左子数组和右子数组合并成一个有序数组。合并的过程中,逐个比较左右两个数组的元素,并将较小的元素添加到结果数组中,直到两个数组都为空。
  4. 返回结果: 最终得到一个完全排序好的数组。

归并排序的关键在于合并过程,也就是如何将两个有序数组合并成一个有序数组。这一过程保持了相等元素的相对顺序,因此归并排序是一种稳定的排序算法。

归并排序的示例

让我们通过一个示例来理解归并排序的工作原理。假设我们有一个整数数组 [5, 2, 9, 3, 4],我们希望按升序排序它。

  1. 分割数组: 首先将数组分成两个子数组 [5, 2][9, 3, 4]
  2. 递归排序: 分别对左子数组 [5, 2] 和右子数组 [9, 3, 4] 递归地应用归并排序。
  • 对左子数组 [5, 2] 进行归并排序,得到 [2, 5]
  • 对右子数组 [9, 3, 4] 进行归并排序,得到 [3, 4, 9]
  1. 合并数组: 合并已排序的左子数组 [2, 5] 和右子数组 [3, 4, 9]
  • 比较左右两个数组的首元素,选择较小的元素 2,将其添加到结果数组。
  • 继续比较,选择 3,将其添加到结果数组。
  • 接着选择 459,按顺序添加到结果数组。
  1. 返回结果: 最终,得到排序后的数组 [2, 3, 4, 5, 9]

归并排序的时间复杂度

归并排序的时间复杂度非常稳定,始终为O(n*log(n)),其中n是数组的长度。这使得它适用于大型数据集和对稳定性有要求的情况。

尽管归并排序的时间复杂度相对较高,但它的性能稳定,对于各种数据集都表现出色。此外,归并排序是一种外部排序的重要算法,用于处理大型文件和数据库。

示例代码

以下是归并排序的示例代码,分别使用Python、Go、Java和C语言编写。

Python 归并排序

def merge_sort(arr):
    if len(arr) <= 1:
        return arr

    mid = len(arr) // 2
    left = arr[:mid]
    right = arr[mid:]

    left = merge_sort(left)
    right = merge_sort(right)

    return merge(left, right)

def merge(left, right):
    result = []
    i = j = 0

    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1

    result.extend(left[i:])
    result.extend(right[j:])
    return result

arr = [5, 2, 9, 3, 4]
sorted_arr = merge_sort(arr)
print("排序后的数组:", sorted_arr)

Go 归并排序

package main

import "fmt"

func mergeSort(arr []int) []int {
    if len(arr) <= 1 {
        return arr
    }

    mid := len(arr) / 2
    left := arr[:mid]
    right := arr[mid:]

    left = mergeSort(left)
    right = mergeSort(right)

    return merge(left, right)
}

func merge(left, right []int) []int {
    result := []int{}
    i, j := 0, 0

    for i < len(left) && j < len(right) {
        if left[i] < right[j] {
            result = append(result, left[i])
            i++
        } else {
            result = append(result, right[j])
            j++
        }
    }

    result = append(result, left[i:]...)
    result = append(result, right[j:]...)
    return result
}

func main() {
    arr := []int{5, 2, 9, 3, 4}
    sorted_arr := mergeSort(arr)
    fmt.Println("排序后的数组:", sorted_arr)
}

Java 归并排序

import java.util.Arrays;

public class MergeSort {
    public static void mergeSort(int[] arr, int left, int right) {
        if (left < right) {
            int mid = (left + right) / 2;
            mergeSort(arr, left, mid);
            mergeSort(arr, mid + 1, right);
            merge(arr, left, mid, right);
        }
    }

    public static void merge(int[] arr, int left, int mid, int right) {
        int n1 = mid - left + 1;
        int n2 = right - mid;

        int[] leftArray = new int[n1];
        int[] rightArray = new int[n2];

        for (int i = 0; i < n1; i++) {
            leftArray[i] = arr[left + i];
        }
        for (int i = 0; i < n2; i++) {
            rightArray[i] = arr[mid + 1 + i];
        }

        int i = 0, j = 0;
        int k = left;
        while (i < n1 && j < n2) {
            if (leftArray[i] <= rightArray[j]) {
                arr[k] = leftArray[i];
                i++;
            } else {
                arr[k] = rightArray[j];
                j++;
            }
            k++;
        }

        while (i < n1) {
            arr[k] = leftArray[i];
            i++;
            k++;
        }

        while (j < n2) {
            arr[k] = rightArray[j];
            j++;
            k++;
        }
    }

    public static void main(String[] args) {
        int[] arr = {5, 2, 9, 3, 4};
        mergeSort(arr, 0, arr.length - 1);
        System.out.print("排序后的数组: ");
        System.out.println(Arrays.toString(arr));
    }
}

C 语言 归并排序

#include <stdio.h>

void merge(int arr[], int left, int mid, int right) {
    int n1 = mid - left + 1;
    int n2 = right - mid;

    int leftArray[n1], rightArray[n2];

    for (int i = 0; i < n1; i++) {
        leftArray[i] = arr[left + i];
    }
    for (int i = 0; i < n2; i++) {
        rightArray[i] = arr[mid + 1 + i];
    }

    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (leftArray[i] <= rightArray[j]) {
            arr[k] = leftArray[i];
            i++;
        } else {
            arr[k] = rightArray[j];
            j++;
        }
        k++;
    }

    while (i < n1) {
        arr[k] = leftArray[i];
        i++;
        k++;
    }

    while (j < n2) {
        arr[k] = rightArray[j];
        j++;
        k++;
    }
}

void mergeSort(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);
    }
}

int main() {
    int arr[] = {5, 2, 9, 3, 4};
    int n = sizeof(arr) / sizeof(arr[0]);
    mergeSort(arr, 0, n - 1);
    printf("排序后的数组: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

以上示例代码展示了不同编程语言中的归并排序算法实现。这些示例帮助你理解归并排序的工作原理,并提供了可供参考和使用的代码示例。归并排序是一种稳定且高效的排序算法,适用于各种应用场景,特别适合对大型数据集进行排序。

标签:归并,int,arr,算法,数组,排序,left
From: https://blog.51cto.com/u_16170163/7474671

相关文章

  • EndNote调整中文、英文参考文献的排序顺序
      本文介绍在EndNote软件中,使得参考文献按照语种排列,中文在前、英文在后的方法。  前期我们在文献管理EndNote软件自定义修改引文输出格式的方法一文中,详细介绍了文献管理软件EndNote的引用格式自定义方法,其中我们设置了将参考文献部分的文章按照文章语种进行排序,而这一设置在......
  • 算法戴高乐计划-01篇
    LCP07.传递信息小朋友A在和ta的小伙伴们玩传信息游戏,游戏规则如下:有n名玩家,所有玩家编号分别为0~n-1,其中小朋友A的编号为0每个玩家都有固定的若干个可传信息的其他玩家(也可能没有)。传信息的关系是单向的(比如A可以向B传信息,但B不能向A传信息)。每轮信息必......
  • 代码随想录算法训练营第八天
    代码随想录算法训练营第八天|LeetCode28(实现strStr())LeetCode459(重复的子字符串)28:实现strStr()LeetCode28(实现strStr())classSolution{publicintstrStr(Stringhaystack,Stringneedle){//构造next数组int[]next=newint[needle.l......
  • speex降噪算法移植及测试
    下载libspeexdspPC上,编译。修改内置demo输入in.pcm,输出out.pcm,用音频分析软件及实测效果OK.#ifdefHAVE_CONFIG_H#include"config.h"#endif#include"speex/speex_preprocess.h"#include<stdio.h>#defineNN160intmain(){  shortin[NN];  inti;  SpeexPre......
  • speexdsp库实现音频3A算法
    speex是音频编解码库,speexdsp是附加的音频DSP库,是音频降噪库,也有回声抑制和自动增益控制功能,即通常说的音频3A算法。现在音频编解码大部分都是使用opus库,很少使用speex进行音频编解码,但还是会使用speexdsp库的3A算法对音频数据进行处理。本例是在ubuntu环境下,C/C++语言,使用Qt进......
  • 算法竞赛文件读写
    freopen使用freopen进行文件读写,可以节约测试时重复输入的时间,用法可以参考官网std::freopen-cppreference.com。程序中使用cin/cout和scanf/printf均可。模板#include<cstdio>usingnamespacestd;intmain(){//提交时记得将这两行注释掉freopen("E:\\c\\in......
  • vu3 列表拖动排序
    <el-tableclass="flex-table"size="medium":border="true"tooltip-effect="dark"highlight-current-row:data="branchTableData"......
  • Lnton羚通视频分析算法平台人员闯入算法检测告警详细介绍
    Lnton羚通的算法算力云平台有以下显著特点:高性能、高可靠性、高可扩展性和低成本。用户可以通过该云平台获取高效、强大的算法计算服务,快速而灵活地运行各种复杂的计算模型和算法。该平台广泛涵盖机器学习、人工智能、大数据分析和图像识别等领域。此外,云平台还提供丰富的算法库和......
  • vue3 elementplus 列表中添加排序功能,移动的时候修改背景色
    <el-tablesize="medium":border="true":data="branchTableData":row-style="changeColor":stripe=falsestyle="width:100%;">......
  • 【理论优化算法】基于理论和优化算法求解单目标优化问题附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......