归并排序(自底向上)

归并排序(自底向上)

算法概述

自底向上归并排序是一种非递归排序算法。它首先把待排序的数组拆分为多个长度为 2 的子序列(不足2的部分也作为一个子序列看待),接着对每个子序列进行排序,保证每个子序列内部是有序的,然后在这个基础上把数组拆分为多个长度为 4 的子序列,对每个子序列进行排序,以此类推,每次迭代子序列的长度翻倍,直到子序列长度能覆盖数组长度,最终完成排序。

算法实现

package main

func SortBU(arr []int) {
  n := len(arr)
  temp := make([]int, n)

  // 对数组中的每 16 个元素进行插入排序处理,16 是一个经验值
  // 数据量少和基本有序的情况下插入排序效率更高
  for i := 0; i < n; i += 16 {
    InsertionSort(arr, i, min(n-1, i+15))
  }

  // 划分子序列,子序列的半长以 16 为起始值(不再重复处理插入排序中已排序的部分),每次翻倍
  for sz := 16; sz < n; sz += sz {
    // 对每个子序列进行归并排序
    for i := 0; i+sz < n; i += 2 * sz {
      // 子序列前一半的最后一个元素大于后一半的第一个元素时,证明子序列内部存在乱序需要进行归并
      if arr[i+sz-1] > arr[i+sz] {
        // min(i+sz+sz-1, n-1) 用于处理 i+sz+sz-1 大于 n-1 的情况
        merge(arr, temp, i, i+sz-1, min(i+sz+sz-1, n-1))
      }
    }
  }
}

func InsertionSort(arr []int, left, right int) {
  for i := left + 1; i <= right; i++ {
    temp := arr[i]
    j := i - 1

    for ; j >= left && arr[j] > temp; j-- {
      arr[j+1] = arr[j]
    }
    arr[j+1] = temp
  }
}

func merge(arr, temp []int, l, mid, r int) {
  // 把 arr 指定位置的元素复制到 temp 保存副本
  // 后续排序时就是取 temp 中指定位置的前半部分和后半部分元素进行比较,出结果后再放到 arr 中合适的位置
  copy(temp[l:r+1], arr[l:r+1])
  // i 为左子序列的起始位置,j 为右子序列的起始位置
  i, j := l, mid+1

  // 对子序列进行排序
  for k := l; k <= r; k++ {
    // 子序列的左边已经处理完毕
    if i > mid {
     arr[k] = temp[j]
     j++
    // 子序列的右边已经处理完毕
    } else if j > r {
     arr[k] = temp[i]
     i++
    } else if temp[i] <= temp[j] {
     arr[k] = temp[i]
     i++
    } else {
     arr[k] = temp[j]
     j++
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值