Attachment 'sort_tape.py'

Download

   1 #!/usr/bin/env python
   2 # coding: utf
   3 '''
   4 «Сортировка магнитных лент». Дан файл («магнитная лента»), содержащий строки, одновременно не умещающиеся в памяти. Требуется отсортировать этот файл построчно (записать отсортированные данные обратно на эту ленту). Для сортировки разрешается открывать небольшое число дополнительных файлов произвольного размера (использовать небольшое число дополнительных «лент»). Вот алгоритм с четырьмя лентами. Назовём отрезком упорядоченную последовательность строк на ленте. При записи отрезка на ленту применяется специальный маркер-разделитель. Сначала разобьем исходную ленту на отрезки и перепишем их на первую вспомогательную ленту. Затем перепишем первые два отрезка на две временные ленты и сольём их в один, добавив на вторую вспомогательную ленту. Повторим процесс, пока все отрезки не кончатся (если остался один, просто допишем его). Поменяем вспомогательные ленты местами. Повторим процесс слияния отрезков до тех пор, пока на ленте-приёмнике не окажется ровно один отрезок. Это и будут отсортированные данные. Перепишем содержимое отрезка на исходную ленту.
   5 '''
   6 
   7 import os, sys, pickle
   8 
   9 NEXT,LAST=True,False
  10 
  11 def joinfile(N1,N2,f):
  12     '''Слить два отсортированных файла с именами N1 и N2 в файл-с-отрезками f'''
  13     f1,f2=file(N1),file(N2)
  14     s1,s2=f1.readline(),f2.readline()
  15     while s1 and s2:
  16         if s1<s2: 
  17             pickle.dump(s1,f)
  18             s1=f1.readline()
  19         else:
  20             pickle.dump(s2,f)
  21             s2=f2.readline()
  22     while s1:
  23         pickle.dump(s1,f)
  24         s1=f1.readline()
  25     while s2:
  26         pickle.dump(s2,f)
  27         s2=f2.readline()
  28 
  29 def slice(name,sname):
  30     '''Превратить файл в файл-с-отрезками.
  31     Вернуть количество отрезков'''
  32     old, N, F = "", 1, file(sname,"w")
  33     for s in file(name):
  34         if s<old:
  35             pickle.dump(NEXT,F)
  36             N+=1
  37         pickle.dump(s,F)
  38         old = s
  39     pickle.dump(NEXT,F)
  40     if N%2 and N>1:     # отрезков должно быть чётное число
  41         pickle.dump(NEXT,F)
  42     pickle.dump(LAST,F)    # последний отрезок
  43     F.close()
  44     return N
  45 
  46 def pour(inflow,Name):
  47     '''Перелить отрезок в файл'''
  48     F=open(Name,"w")
  49     s=pickle.load(inflow)
  50     while type(s) is str:
  51         F.write(s)
  52         s=pickle.load(inflow)
  53     F.close()
  54     return s
  55 
  56 def junksort(name):
  57     '''Сортировка слиянием с использованием четырёх дополнтельных файлов'''
  58     In, Out, Name1, Name2 = name+".in", name+".out", name+".1", name+".2"
  59     N=slice(name,Out)
  60     while N>1:
  61         print N
  62         os.rename(Out,In)
  63         FIn, FOut, N = file(In,"r"), file(Out,"w"), 0
  64         while pour(FIn,Name1) and pour(FIn,Name2):
  65             joinfile(Name1,Name2,FOut)
  66             N+=1
  67             pickle.dump(NEXT,FOut)
  68         if N%2 and N>1: pickle.dump(NEXT,FOut)
  69         pickle.dump(LAST,FOut)
  70         FOut.close()
  71     F=file(Out,"r")
  72     pour(F,name)
  73     for n in In, Out, Name1, Name2:
  74         os.unlink(n)
  75 
  76 junksort(sys.argv[1])

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.