外部排序概念

对大文件进行排序,因为文件中的记录很多、信息量庞大,无法将整个文件复制到内存中进行排序

需要将带排序的记录存储在外存上,排序时再把一部分一部分地调入内存进行排序,在排序过程中需要多次进行内存和外存之间的交换

image-20230304150642724

外部排序的方法

image-20230304150813748

优化方式

优化主要考虑减少访问磁盘的次数

访问磁盘的次数=归并趟数S=logkr

  1. 增加k(归并路数)

    • 无脑增大只会增加内存消耗和内部排序的时间
    • 为了减少k增大刀子内部归并时比较次数增多的影响,可以使用败者树
  2. 减少r(初始归并段个数)

  3. 上一步如果使用置换-选择排序,会导致初始归并段的大小不同,可以优化初始归并段的顺序来降低访问磁盘的次数

 

败者树

image-20230304153107354image-20230304154831232

这种对战树就是败者树

上图败者树生成过程
  1. 先把每个归并段段第一个数字放到败者树的叶子结点
    • 这里的归并段是已经读取到内存中的,n个归并段就是n路归并
    • 叶子结点可以放到一个数组里,就像前面的堆排序,0号位用来存放冠军结点,参考下面的图,ls数组就是存放的叶子结点
  2. 27和12决斗(比较),12更小所以27留下(这里找最小),即留在图上的1的位置
  3. 1和17决斗(比较),1更小所以17留在4的位置
  4. 此时12和1都晋级到数字2那一层,12和1决斗(比较),1胜出所以12留在图上2的位置
  5. ....
  6. 直到最终决斗出一个最小的放在3那个位置
  7. 图中的序号对应归并段的位置,最小的是3也就是归并段3的第一个数最小,将归并段3的第一个数字放到输出缓冲区
  8. 将归并段3的下一位数字放到原来的3号位置(叶子结点那里),再与1,2,5进行决斗(比较),选出新的冠军(最小值)

败者树的实现

置换-选择排序

image-20230304175923790image-20230304180218979image-20230304180555769image-20230304185116465

最佳归并树

image-20230304191243373image-20230304191604700

上图仅为2路归并时的最佳归并树,如果是多路归并则需要使用k叉哈夫曼树

错题集

  1. image-20230304193406054

    答案与解析:
    答案: B
    解析:
    工作区能容纳600个记录=>一共有37500/600=625个归并段
    直接套公式可以S=logmr=log5625=4
    不会套公式可以一步步算
    第一趟归并排序会合并成625/5=125个归并段
    第二趟归并排序会合并成125/5=25个归并段
    第三趟归并排序会合并成25/5=5个归并段
    第四趟归并排序会合并成5/5=1个归并段
  1. image-20230304194157782

    答案与解析:
    答案: C B
    解析:
    传统顺序选(一个个比较):每一次都要比较4次才能选出一个最小值,一共需要99次才能选完100个记录,所以总的比较次数为4*99=396次
    使用败者树:树高h=⌈log25⌉=3,每一次都需要比较3次才能选出一个最小值,一共需要比较100次,所以总的比较次数为3*100=300次