首页 > 编程语言 >算法——初级排序算法之归并排序

算法——初级排序算法之归并排序

时间:2023-08-12 21:33:13浏览次数:35  
标签:归并 temp int lo Comparable 算法 排序 arr

介绍

将两个有序的数组归并成一个更大的有序数组,这种算法叫归并排序

特点

优点:能够保证将任意长度为N的数组排序所需时间和NlogN成正比

缺点:所需的额外空间和N成正比

1、**原地归并 **

实现归并的一种直截了当的办法是将两个不同的有序数组归并到每三个数组中,两个数组中的元素应该都实现了Comparable接口。实现的方法:创建一个适当大小的数组然后将两个输入数组中的元素一个个从小到大放入这个数组中。

// 原地归并 抽象
public static void merge(Comparable[] a, int lo, int mid, int hi, Comparable[] temp) {
  // 将a[lo..mid] 和 a[mid +1..hi] 归并
  int i = lo, j = mid + i;
  for (int k = lo; k <= hi; k++) {
    temp[k] = a[k];
  }

  for (int k = lo; k <= hi; k++) {
    if (i > mid && j <= hi) a[k] = temp[j++];
    else if (j > hi) a[k] = temp[i++];
    else if (less(temp[j], temp[i])) a[k] = temp[j++];
    else a[k] = temp[i++];
  }


}

2、自顶向下归并

package algorithm.sort.merge;

import java.util.Arrays;

/**
 * 描述:归并排序 原地归并\自顶向下\自底向上
 * Created by zjw on 2021/6/27 22:20
 */
public class MergeSort {


    public static void main(String[] args) {
        Integer[] arr = {1, 2, 3, 4, 5, 22, 2, 12, 13, 21, 9};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }

    // 原地归并
    public static void merge(Comparable[] a, int lo, int mid, int hi, Comparable[] temp) {
        // 将a[lo..mid] 和 a[mid +1..hi] 归并
        int i = lo, j = mid + 1;
        for (int k = lo; k <= hi; k++) {
            temp[k] = a[k];
        }

        for (int k = lo; k <= hi; k++) {
            if (i > mid) a[k] = temp[j++];
            else if (j > hi) a[k] = temp[i++];
            else if (less(temp[j], temp[i])) a[k] = temp[j++];
            else a[k] = temp[i++];
        }


    }

    // 自顶向下的归并
    public static void sort(Comparable[] arr) {
        Comparable[] temp = new Comparable[arr.length]; // 一次性分配内存空间\避免递归中频繁开辟空间
        // sortDown(arr, 0, arr.length - 1, temp);
        sortUp(arr, temp);

    }

    // 自顶向下的归并
    public static void sortDown(Comparable[] arr, int lo, int hi, Comparable[] temp) {
        // 将数组a[lo..hi]排序
        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;

        sortDown(arr, lo, mid, temp);// 排序左半边 左边归并排序,使得左子序列有序
        sortDown(arr, mid + 1, hi, temp);// 排序右半边 右边归并排序,使得右子序列有序
        merge(arr, lo, mid, hi, temp); // 归并结果
    }

    // 自底向上的归并
    public static void sortUp(Comparable[] arr, Comparable[] temp) {
        // 进行lgN次两两归并
        int N = arr.length;
        temp = new Comparable[N];
        for (int sz = 1; sz < N; sz = sz + sz) {
            for (int lo = 0; lo < N - sz; lo += sz + sz) {
                merge(arr, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, N - 1), temp);
            }
        }
    }


    private static boolean less(Comparable v, Comparable w) {
        return v.compareTo(w) < 0;
    }
}

3、自底向上归并

// 自底向上的归并
    public static void sortUp(Comparable[] arr, Comparable[] temp) {
        // 进行lgN次两两归并
        int N = arr.length;
        temp = new Comparable[N];
        for (int sz = 1; sz < N; sz = sz + sz) {
            for (int lo = 0; lo < N - sz; lo += sz + sz) {
                merge(arr, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, N - 1), temp);
            }
        }
    }

总结

当数组长度为2的幂时,向上和向下比较次数和数组访问次数是一样的,只是顺序不同。

自底向上的归并排序比较适合用链表组织的数据。

标签:归并,temp,int,lo,Comparable,算法,排序,arr
From: https://blog.51cto.com/u_11906056/7062024

相关文章

  • 某公司笔试题 - 字符串排序(附python代码)
    #给定n个字符串,请对n个字符串按照字典序排列。#数据范围:1<=n<=1000,字符串长度满足1<=len<=100times=int(input("请输入字符串的个数:"))iftimes>=1andtimes<=1000:dicts={}print("请输入字符串,回车键切换输入下一个字符串:")foriinrange(......
  • 压缩算法
    思路因为这个字符串可以被多层压缩,所以我们要找到最里层的中括号。刚开始的思路是利用栈,从前往后找,遇到'['的时候,将元素入栈,遇到']'的时候,让元素出栈,计算出解压后的字符串,然后继续往后遍历,一直到栈为空。但是编码的过程中发现这种办法太过复杂。后来发现,只要从后往前遍历,找到的......
  • 【BP回归预测】基于粒子群算法优化BP神经网络实现数据回归预测附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 2023-08-12:用go语言写算法。实验室需要配制一种溶液,现在研究员面前有n种该物质的溶液,
    2023-08-12:用go语言写算法。实验室需要配制一种溶液,现在研究员面前有n种该物质的溶液,每一种有无限多瓶,第i种的溶液体积为v[i],里面含有w[i]单位的该物质,研究员每次可以选择一瓶溶液,将其倒入另外一瓶(假设瓶子的容量无限),即可以看作将两个瓶子内的溶液合并,此时合并的溶液体积和物质含量......
  • 【总结】排序算法的时间复杂度和空间复杂度
    排序算法的时间复杂度和空间复杂度最好时间复杂度最坏时间复杂度平均时间复杂度空间复杂度是否为稳定排序是否为原地排序冒泡排序$O(n)$初始数组正序$O(n^2)$初始数组逆序$O(n^2)$$O(1)$原地使用数组,无额外内存开销是是插入排序是是选择排序$O(n......
  • AXI传输总结+页面置换算法+不定态判定+PATH管理
    AXI传输总结AXI这部分我没有深入解除过,只是多多少少摸一下看下数据路径有没有传过去,总感觉不到难点在哪里,不就是一个传输协议吗?这个是soc设计方法与实现中提供的附录,可供参考,但是有版本错误(AXI4不支持写的交织,没有WID)https://www.hxedu.com.cn/hxedu/w/inputVideo.do?qid=5a79......
  • 冒泡排序
    #include<iostream>usingnamespacestd;intmain(){intt,a[4];for(inti=1;i<=3;i++){cin>>a[i];}for(inti=1;i<=2;i++){for(intj=1;j<=3-i;j++){if(a[j]<a[j+1]){t......
  • 常用的排序算法
    总结基于比较的排序(从小到大排序)冒泡排序GO实现funcMySort(arr[]int)[]int{//冒泡//大的往后冒fori:=0;i<len(arr);i++{forj:=0;j<len(arr)-1-i;j++{ifarr[j]>arr[j+1]{arr[j],arr......
  • 快速排序(NB)
    博客地址:https://www.cnblogs.com/zylyehuo/#_*_coding:utf-8_*_defpartition(li,left,right):tmp=li[left]whileleft<right:whileleft<rightandli[right]>=tmp:#从右面找比tmp小的数right-=1#往左走一步l......
  • 交换排序
    数据结构--交换排序基本思想:两两比较,如果发生逆序则交换,直到所有记录都排好序为止.冒泡排序每趟不断将记录两两比较,并且按照"前小后大"规则交换.冒泡排序的过程演示n个记录,需要比较n-1趟.第m躺需要比较n-m次冒泡排序算法描述还可以继续优化:某一趟比较时不出现......