Главная Терминология Хоора 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 [ 44 ] 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 последнего элемента последней серии каждой ленты. этого мы вводим переменную last: array[/apmo] of integer Теперь алгоритм распределения можно представить следующим образом: repeat selecttape; if lasAj] < /ОТ -key then продолжение прежней серии ; (2.Щ copyrun; lastlj} := /ОТ -key mm eofWO) Здесь содержится очевидная ошибка: мы забыли о том что last[j] получает (определенное) значение только после переписи первой серии! Правильное решение состоит в том, что вначале распределяется по одной серии на каждую нз п-1 лент без обращения к last[j]. Оставшиеся серии рас- пределяются согласно (2.49): while -neof(fO) do bein selecttape; if Ш[Д < /ОТ .key then l egin [продолжение прежней серии] copyrun; (2.49) if eofifO) then d[j1 := dlJ] + 1 else copyrun end else copyrun Предполагается, что присваивание значений last[j] включено в процедуру copyrun. Теперь мы, наконец, готовы взяться за основной алгоритм многофазной сортировки слиянием. Его принципиальнав структура подобна основной части программы п-путевого слияния: имеется внешний цикл, в теле которого сливаются серии, пока не будут исчерпаны все входные данные, внутренний цикл, в теле которого сливается по одной серии с каждо' входной ленты, и самый внутренний цикл, в теле которог выбирается начальный ключ и элемент передается в выхоД' ной файл. Принципиальные отличия следующие: 1. На каждом проходе имеется только одна выходная ленте, вместо п/2. 2. Вместо переключения п/2 входных и п/2 выходных леи' - после каждого прохода ленты чередуются. Этю достигаете* . с помощью карты ленточных индексов t. ццсло ВХОДНЫХ лент меняется от серии к серии; в начале каждой серии оно определяется по счетчикам di фиктивных серий. Если di > О для всех i, то п - 1 фиктивных серий сливаются в одну фиктивную серию при помощи простого увеличения счетчика dn выходной ленты. В противном случае со всех лент, у которых di = О, сливается по одной серии, а для всех остальных лент di уменьщается, т означает исключение одной фиктивной серии. Число входных лент, участвующих в слиянии, мы обозначаем через к. 4 Невозможно установить окончание фазы при помощи состояния конца файла (п-1)-й ленты, поскольку могут понадобиться дальнейшие слияния, в которых участвуют фиктивные серии с этой ленты. Вместо этого теоретически необходимое число серий определяется по коэффициентам а,-. Коэффициенты а,- были вычислены на фазе распределения; теперь их можно вычислить в обратном порядке . Теперь, согласно этим правилам, сформулируем основную часть алгоритма многофазной сортировки, предполагая, что все п-1 лент с начальными сериями перемотаны на начало и установлены начальные значения в карте ленточных индексов ti = i: repeat [слияние с t[l] ... t[n - 1] на t[n]] z := a[n-l]; ф] := 0; rewnte(J\t[nJ[); repeat к := 0; [слияние одной серии] [определение числа к входных лент, участвующих в слиянии^ for I := 1 to и-1 do if d[i\ > Q tlien d[i] := d[i] -1 else begin к :=k+l; ta[k] := t[q end ; if = 0 then d[n] := d[n] + 1 else слияние одной действительной серии с t[l] .. J[k] z := z-1 until г = 0; reset(f[t[nS); переключение лент в карте t; вычисление й[/] для следующего уровня ; rewrite(J[t[nS); level := level - 1 til level = 0; опгсортированный файл находится на ([Ц ] (2.50) Операция действительного слияния почти идентична программой п-путевой сортировки слиянием, единственная program poly sort (output); {многофазная сортировка с n лентами} const к = 6; {числолент} type item = record кеу'. integer end ; tape == file otitem; tapeno - 1., и; var leng, rand: integer; [используются оля формирования фай/w) eot: boolean; buf: item; /0; tape; if 0-входная лента со случайными числами] /; array [1.. и] of tape; procedure/to (var/: tape; n: tapeno); mtrmTeger; begin z := 0; writeln (TAPE, n: 2); while -neof(f) do Hegin read(f, buf); write(ouiput, buf.key: 5); z z+l; if z = 25 then begin TV 7e/n (oi/(pMf); z :- 0 end end ; if z 9b Othenw/Ve/nXowPOJ rcset(f) end { if}-; fTocedate polyphasesort; var i,jx,tn: tapeno; k, level: integer; a, d: array [й/)еио] of integer; [аЩ-идеальное число серий на ленте]] {йЩ-число фиктивных серий на ленте j] dn,xin,z: integer; last: array [tapeno] of integer; {/с5/[/]-ключ конечной серии на менте j] t,ta: array [tapeno] of tqpeno; [карты номеров Лент] procedure 5e/ec/rape; var i: tapeno; z: integer; begin if 4;1 < 4У+1] tben J :== j+1 else begin if d[j] = Otisen begin := level + 1; z :== |