zoukankan      html  css  js  c++  java
  • 外部排序:多路归并树

    定义:

    1、按可用内存大小,将外存上的记录文件分成若干个归并段 (segments)

    2、依次读入内存并利用有效的外部排序方法进行排序

    3、将排序后的有序子文件写入外存

    实现:

    利用败者树进行k路归并,使得每次归并在k个记录中选出最小记录仅需进行次(二叉树的深度)比较,从而使总的归并时间为。其中,m为初始归并段个数,n为总记录数,每次比较时间。

    败者树:

    典型的4路败者树如下图:

    ----------à

    直观的,败者树是一棵完全二叉树,可由数组保持。其中根节点保存一次比较中的冠军;叶节点保存4个归并段的输入流;非叶结点保存一次比较中的败者。

    难点1:一轮比较选出最小关键记录并调整败者树

    调整的发起点:值发生变化的叶节点,必然使对应的父节点发生变化。注意,父节点中记录的败者必然是另一棵子树的胜者,但是败给了本子树的胜者,如

    调整:

    1、i保存前一次比较的胜者,与的败者比较

        If i失败: , 发生互换

    2、如此递归的向根节点调用,直到根节点,将i中的冠军计入

    难点2:败者树的初始化

    1、将非叶结点初始化为可能的最小值(冠军)

    2、由调整败者树

    注意点:

    每个归并段内的数据是有序的,这与归并排序是一致的。并且归并段的最后需要一个全局最小的"哨兵",防止归并段读空(仔细想想),并且当冠军为"哨兵"时,程序退出。

    思想:以空间保存历次比较结果,将一般k-路归并选择一次最小值的k-1次操作变为,典型的时空互换思想。

    代码:

    1. import java.io.*;
    2.  
    3. public class LoserTree {
    4.  
    5.    public static void main(String[] args) {
    6.  
    7.       PrintWriter[] data = new PrintWriter[LoserTree.K];
    8.       BufferedReader[] segments = new BufferedReader[LoserTree.K];
    9.  
    10.  
    11.       try {
    12.  
    13.          for (int i = 0; i < LoserTree.K; i++) {
    14.  
    15.             data[i] = new PrintWriter(new FileWriter(i + ".txt"));
    16.          }
    17.  
    18.          for (int k = 0; k < 5; k++) {
    19.  
    20.             for (int i = 0; i < 5; i++) {
    21.  
    22.                data[k].println(21 - 5 * k + i);
    23.             }
    24.  
    25.             data[k].println(LoserTree.MAXKEY);
    26.          }
    27.  
    28.          for (int i = 0; i < LoserTree.K; i++) {
    29.  
    30.             data[i].close();
    31.          }
    32.  
    33.          for (int i = 0; i < LoserTree.K; i++) {
    34.  
    35.             segments[i] = new BufferedReader(new FileReader(i + ".txt"));
    36.          }
    37.  
    38.          LoserTree Sorter = new LoserTree();
    39.  
    40.          Sorter.merge(segments);
    41.  
    42.          for (int i = 0; i < LoserTree.K; i++) {
    43.  
    44.             segments[i].close();
    45.          }
    46.  
    47.       } catch (Exception e) {
    48.  
    49.          e.printStackTrace();
    50.       }
    51.  
    52.    }
    53.  
    54.    static final int K = 5;
    55.    static final int MINKEY = -100;
    56.    static final int MAXKEY = 100;
    57.  
    58.    public int[] LS = new int[K];
    59.    public int[] b = new int[K + 1];
    60.  
    61.    PrintWriter result;
    62.  
    63.    public void merge(BufferedReader[] in) {
    64.  
    65.       try {
    66.          result = new PrintWriter(new File("result.txt"));
    67.  
    68.          for (int i = 0; i < K; i++) {
    69.  
    70.             input(in[i], i);
    71.          }
    72.  
    73.          create();
    74.  
    75.          int q;
    76.  
    77.          while (b[LS[0]] != MAXKEY) {
    78.  
    79.             q = LS[0];
    80.  
    81.             output(q);
    82.  
    83.             input(in[q], q);
    84.  
    85.             adjust(q);
    86.  
    87.          }
    88.  
    89.          result.close();
    90.  
    91.       } catch (Exception e) {
    92.          // TODO Auto-generated catch block
    93.          throw new RuntimeException(e);
    94.       }
    95.  
    96.  
    97.    }
    98.  
    99.    private void create() {
    100.  
    101.       b[K] = MINKEY;
    102.  
    103.       for (int i = 0; i < K; i++) {
    104.  
    105.          LS[i] = K;
    106.       }
    107.  
    108.       for (int i = K-1; i > -1; i--) {
    109.  
    110.          adjust(i);
    111.       }
    112.    }
    113.  
    114.    private void adjust(int i) {
    115.  
    116.       int parent = (i + K) / 2;
    117.  
    118.       int temp;
    119.  
    120.       while (parent > 0) {
    121.  
    122.          if (b[i] > b[LS[parent]]) {
    123.  
    124.             temp = LS[parent];
    125.             LS[parent] = i;
    126.             i = temp;
    127.          }
    128.  
    129.          parent = parent / 2;
    130.       }
    131.  
    132.       LS[0] = i;
    133.  
    134.  
    135.    }
    136.  
    137.    private void input(BufferedReader in, int i) {
    138.  
    139.       try {
    140.  
    141.          b[i] = Integer.valueOf(in.readLine());
    142.  
    143.       } catch (Exception e) {
    144.          // TODO Auto-generated catch block
    145.          throw new RuntimeException(e);
    146.  
    147.       }
    148.    }
    149.  
    150.    private void output(int i) {
    151.  
    152.       result.println(b[i]);
    153.       result.flush();
    154.    }
    155. }
  • 相关阅读:
    Ubuntu 16 编译装python2.7
    配置ubunto 流量使用限制 python 实现简单 http server
    vnstat 流量统计 并附带一个小 php 查看流量的页面
    ubunto 免输入密码 登录 putty ssh-keygen
    nes 红白机模拟器 第5篇 全屏显示
    arm 添加 samb 文件共享
    arm 添加 ftp server 之 bftpd
    Tga图片格式分析以及程序实现
    领导力:刘邦的管理之道
    AS3:辨析ROLL_OVER与MOUSE_OVER,ROLL_OUT与MOUSE_OUT
  • 原文地址:https://www.cnblogs.com/zjgtan/p/3316962.html
Copyright © 2011-2022 走看看