当前位置: 首页 > article >正文

归并排序 - 非递归实现


import java.util.Arrays;

/**
 * @title MergeSortByNonRecursion
 * @description 归并排序,非递归实现
 * author zzw
 * version 1.0.0
 * create 2024/10/23 22:17
 **/
public class MergeSortByNonRecursion {

    public static void main(String[] args) {
        int[] nums = {5, 1, 1, 2, 0, 0};
        new MergeSortByNonRecursion().sortArray(nums);
        System.out.println(Arrays.toString(nums));
    }

    public int[] sortArray(int[] nums) {
        sort(nums);
        return nums;
    }

    /**
     * 归并排序,非递归处理<br/>
     * <ol>
     *     <li>每次将相邻的两个有序数组进行合并</li>
     *     <li>先从只有一个节点的数组开始(一个节点默认有序,无需做其他处理),从做向右合并</li>
     *     <li>将数组处理完一遍后,将节点个数增大一倍,将合并好的子数组再进行合并</li>
     * </ol>
     *
     * @param arr 排序数组
     */
    public static void sort(int[] arr) {
        // 每次用来合并的子数组中的元素个数,每次增加一倍
        for (int i = 1; i < arr.length; i <<= 1) {
            // 默认左侧数据的起始节点从0开始
            int leftIndex = 0;
            // 计算出中间节点
            int mid = leftIndex + i - 1;
            // 只有中间节点小于数组长度减一的时候,才能保证左右两侧数组都存在数据,这样才需要进行数组的合并
            while (mid < arr.length - 1) {
                // 计算出右侧子数组的最后一个节点下标
                // 该下标取中间节点加子数组长度个数 和 总数组长度的最小值,避免数组越界
                int right = Math.min((mid + i), arr.length - 1);
                // 进行数组合并
                merge(arr, leftIndex, mid, right);
                // 计算下一组需要合并的子数组的左侧数组起始位置
                leftIndex = right + 1;
                // 计算下一组需要合并的子数组的左侧数组终止位置
                // 这里计算用于判断是否还有数据数据放入右侧数组进行合并
                mid = leftIndex + i - 1;
            }
        }
    }


    /**
     * 合并两个有序数组
     *
     * @param arr   两个有序数组所在的有序数据
     * @param left  左侧有序数据在arr数组中的起始位置
     * @param mid   左侧有序数组在arr数组中的终点位置
     * @param right 右侧有序数组在arr数组中的终点位置,起始位置在mid+1处
     */
    public static void merge(int[] arr, int left, int mid, int right) {
        // 使用一个临时数据存放合并后的数据
        int[] tmp = new int[right - left + 1];
        // 临时数据数据合并到的下标
        int i = 0;
        // 左侧有序数据处理到的位置
        int lIndex = left;
        // 右侧有序数据处理到的位置
        int rIndex = mid + 1;

        // 比较左、右两侧的有序数组,谁的值小,将谁放到临时数组中,
        // 然后将临时数组、取值的哪个数组的处理下标向后移动
        // 直到左、右两侧的数组有一个处理完,停止此次处理
        while (lIndex <= mid && rIndex <= right) {
            tmp[i++] = arr[lIndex] <= arr[rIndex] ? arr[lIndex++] : arr[rIndex++];
        }

        // 如果左侧的有序数组没有处理完,将左侧数组的剩余数据放入临时数组中
        while (lIndex <= mid) {
            tmp[i++] = arr[lIndex++];
        }

        // 如果右侧的有序数组没有处理完,将右侧数组的剩余数据放入临时数组中
        while (rIndex <= right) {
            tmp[i++] = arr[rIndex++];
        }

        // 将临时数组中的数据放回原来的数据中
        for (int j = 0; j < i; j++) {
            arr[j + left] = tmp[j];
        }
    }

}


http://www.kler.cn/news/362299.html

相关文章:

  • 关于 FusionPBX
  • 探索 Web Audio API 的奇妙世界
  • 基于PERL语言的MS中CASTEP模块批量提交计算脚本
  • Hadoop 踩坑汇总
  • Java项目-基于springboot框架的学习选课系统项目实战(附源码+文档)
  • 数据库表的创建
  • 代码随想录刷题Day8
  • 基于SSM汽车零部件加工系统的设计
  • bindService 流程学习总结
  • PTA L1系列题解(C语言)(L1_089 -- L1_096)
  • JZ2440开发板——MMU与Cache
  • 如何使用Git推送本地搭建的仓库以及远程克隆的仓库
  • golang中的上下文
  • 滚雪球学Redis[7.4讲]:Redis在分布式系统中的应用:微服务与跨数据中心策略
  • 016_基于python+django网络爬虫及数据分析可视化系统2024_kyz52ks2
  • Python 应用可观测重磅上线:解决 LLM 应用落地的“最后一公里”问题
  • python如何基于numpy pandas完成复杂的数据分析操作?
  • 华企盾对当前网络安全挑战与应对策略探讨
  • LeetCode102. 二叉树的层序遍历(2024秋季每日一题 43)
  • 毕业设计项目系统:基于Springboot框架的心理咨询评估管理系统,完整源代码+数据库+毕设文档+部署说明
  • python将1格式化为01
  • 思科网络设备命令
  • 9个用于测试自动化的最佳AI测试工具(2024)
  • NoSQL数据库分类简述
  • DSVPN简介与应用
  • Stable Diffusion Web UI 大白话术语解释 (二)