• 贪心算法(三)——最佳合并模式


    问题描述

    给定n个有序文件,每个文件的记录数分别为w1~wn,请给出一种两两合并的方案,使得总合并次数最少。

    注意:
    1. 外排序算法是将多个有序文件合并成一个有序文件的过程。
    2. 在一次合并的过程中,两个文件中的所有记录都需要先从文件中读入内存,再在内存中排序,最后将排序的结果写入文件中。
    3. 假设两个待排序文件记录数分别为n、m,那么将这两个文件合并成一个有序的文件需要进行n+m次读写。

    问题转化

    n个文件两两合并的过程可以用一棵扩充二叉树来表示。因为扩充二叉树只有度为2或0的节点,没有度为1的节点,这符合两两合并的过程。

    在这棵扩充二叉树中:
    1. 方形节点(外界点)表示原始的文件,圆形节点(内节点)表示合并过程中的文件;
    2. 节点的权值表示文件的记录数
    因此,n个文件合并过程的总读写次数为带权外路径长度之和。
    要求最小的合并次数即为求最小的带权外路径长度之和。
    因此,问题就转化为『如何求扩充二叉树的最小加权路径』。
    这个问题可以用哈夫曼算法解决。

    哈夫曼算法

    思路

    若要使得带权外路径长度最小,可以将权值大的节点尽量靠近根节点,这样路径短一些;而权值小的节点可以适当远离根节点,因为权值小,外路径稍微长一点也没事。

    伪代码

    1. 用一个优先权队列存储所有的初始节点;
    2. 从队列中选出两个权值最小的节点,将它们的和作为它们的根节点,并放入队列中;
    3. 循环这个过程,直到队列中只有一个节点为止,此时具有最小带权路径的扩充二叉树构造完毕!此时带权外路径长度即为最小的读写次数。

    代码实现

    1. /**
    2. * 构造二叉树的节点类
    3. */
    4. class TreeNode{
    5. int val;
    6. TreeNode left;
    7. TreeNode right;
    8. TreeNode(int val){
    9. this.val = val;
    10. }
    11. }
    • 1
    1. /**
    2. * 构造哈夫曼树
    3. * @param w:所有节点的权值
    4. * @return 哈夫曼树的根节点
    5. */
    6. TreeNode hfmTree(int[] w){
    7. // 将所有节点存入优先权队列,按照权值递增排序
    8. PriorityQueue<TreeNode> queue = new PriorityQueue<>(w.length, new Comparator<TreeNode>(){
    9. public int compare(TreeNode t1,TreeNodet2){
    10. return t1.val-t2.val;
    11. }
    12. });
    13. for(int i=0; i<w.length; i++){
    14. queue.offer(new TreeNode(w[i]));
    15. }
    16. // 构造哈夫曼树
    17. while( queue.size()>1 ){
    18. // 弹出最小的两个节点
    19. TreeNode node1 = queue.poll();
    20. TreeNode node2 = queue.poll();
    21. // 构造父节点
    22. TreeNode father = new TreeNode(node1+node2);
    23. father.left = node1;
    24. father.right = node2;
    25. // 父节点入队
    26. queue.offer( father );
    27. }
    28. return queue.poll();
    29. }
  • 相关阅读:
    pycharm中做web应用(14)基于Django和mysql 做用户登录验证4
    设计模式 -- 单例模式(Singleton Pattern)
    光学知识整理-偏振光
    589页22万字城市智慧应急指挥中心大数据信息化系统整体设计方案
    【LeetCode每日一题】——905.按奇偶排序数组
    Spring Cloud Alibaba(Nacos+Open Feign)微服务项目如何在本地调试,每次都调用本地的服务?
    OpenYurt环境搭建(遇到的各种坑和解决办法)
    【mysql】出现 slow sql 问题及建议
    数据结构之二叉搜索树
    OpenCV之稠密光流
  • 原文地址:https://blog.csdn.net/liuliuhelingdao/article/details/128057614