- Код: Выделить всё
- program lab3;
 uses Crt;
 const
 chis=['1'..'2'];{Массив для работы меню}
 type
 PInf = ^TInf;
 TInf = record {Запись для элемента очереди}
 num:Integer; {Число }
 next:PInf; {Указатель на следующий элемент очереди}
 end;
 var
 c,m:Longint; {Количество операций сравнения и пересылок}
 key:char; {Переменная для работы меню}
 keys,kn:integer;
 ftext:text; {Переменная для работы с текстовым файлом}
 txt_filename:string[9]; {Переменная для определения имени файла}
 function IsQueueEmpty(qHead, qTail:PInf):Boolean;{Функция проверки очереди на пустоту}
 begin
 IsQueueEmpty:=qHead=nil;
 end;
 procedure SetQueueNext(var qHead, qTail:PInf; next:PInf);{Процедура устанавливает следующий элемент очереди}
 begin
 if IsQueueEmpty(qHead, qTail) then begin
 qHead:=next
 end
 else begin
 qTail^.next:=next;
 end;
 qTail:=next;
 end;
 procedure AddQueueNext(var qHead, qTail:PInf; num:Integer);{Процедура добавления нового элемента в очередь}
 var
 p:PInf;
 begin
 New(p);
 p^.num:=num;
 p^.next:=nil;
 SetQueueNext(qHead, qTail, p);
 end;
 procedure EmptyQueue(var qHead, qTail:PInf);{Процедура очистки очереди}
 begin
 qHead:=nil;
 qTail:=nil;
 end;
 procedure RandomQueue(var qHead, qTail:PInf);{Процедура заполнения очереди случайными числами от 0 до 99}
 var
 i:Integer;
 begin
 Randomize;
 for i:=1 to kn do
 AddQueueNext(qHead, qTail, Random(100));
 end;
 procedure pr_DirectFusion(var qHead, qTail:PInf); {Процедура сортировки очереди методом прямого слияния}
 var
 aHead:array[0..1] of PInf; {Указатели на начала рабочих очередей }
 aTail:array[0..1] of PInf; {Указатели на концы рабочих очередей }
 cHead:array[0..1] of PInf; {Указатели на начала очередей для слияния }
 cTail:array[0..1] of PInf; {Указатели на концы очередей для слияния }
 qr:array[0..1] of Integer; {Размеры серий для рабочих очередей }
 i,k,n,p:Integer;
 p1:PInf;
 begin
 c:=0;
 m:=0;
 for i:=0 to 1 do
 EmptyQueue(aHead[i], aTail[i]);
 n:=0;
 k:=0;
 p1:=qHead;
 while p1<>nil do begin {Делаем расщепление очереди на 2 очереди}
 SetQueueNext(aHead[k], aTail[k], p1);
 Inc(m);
 Inc(n);
 k:=1-k; {Меняем очередь на другую }
 p1:=p1^.next;
 end;
 for k:=0 to 1 do
 aTail[k]^.next:= nil;
 p:=1; {Начинаем основной алгоритм сортировки }
 
 while p<n do begin
 for k:=0 to 1 do
 EmptyQueue(cHead[k], cTail[k]);
 i:=0;
 {Пока в рабочих очередях есть элементы }
 while (aHead[0]<>nil) or (aHead[1]<>nil) do begin
 for k:=0 to 1 do begin
 qr[k]:=0;
 if aHead[k] <> nil then
 qr[k]:=p;
 end;
 {Реализовываем алгоритм слияния }
 while (qr[0] > 0) and (qr[1] > 0) do begin
 case aHead[0]^.num < aHead[1]^.num of
 True:k:=0;
 False:k:=1;
 end;
 Inc(c);
 SetQueueNext(cHead[i], cTail[i], aHead[k]);
 Inc(m);
 {Перемещаем указатель начала рабочей очереди вперед }
 aHead[k]:=aHead[k]^.next;
 if aHead[k] <> nil then
 Dec(qr[k])
 else
 qr[k]:=0;
 end;
 k:=-1;
 if qr[0] > 0 then {Если в рабочей очереди 0 еще остались элементы }
 k:=0
 else if qr[1] > 0 then {Если в рабочей очереди 0 еще остались элементы }
 k:=1;
 if k in [0,1] then
 while (qr[k]>0) and (aHead[k]<>nil) do begin
 SetQueueNext(cHead[i],cTail[i],aHead[k]);
 Inc(m);
 aHead[k]:=aHead[k]^.next;
 Dec(qr[k]);
 end;
 i:=1-i;
 end;
 
 for k:=0 to 1 do begin
 cTail[k]^.next:=nil;
 end;
 
 for k:=0 to 1 do begin
 aHead[k]:=cHead[k]; {Получаем новые рабочие очереди }
 end;
 p:=2*p; {Увеличиваем размер серии }
 end;
 qHead:=cHead[0];
 qTail:=cTail[0];
 end;
 { Возвращает из числа num цифру с номером digitNo, при условии, что
 в числе всего digitsNumber цифр }
 function Digit(num, digitsNumber, digitNo: Integer): Integer;
 var
 i:Integer;
 s:String;
 begin
 Str(num,s);
 while Length(s) < digitsNumber do
 s:='0'+s;
 Digit:= Ord(s[digitNo]) - Ord('0');
 end;
 procedure ConcatQueues(var q1Head, q1Tail: PInf; q2Head, q2Tail: PInf);{Процедура Объединения двух очередей}
 begin
 if IsQueueEmpty(q2Head, q2Tail) then
 Exit;
 if IsQueueEmpty(q1Head, q1Tail) then begin
 q1Head := q2Head;
 q1Tail := q2Tail;
 end
 else begin
 q1Tail^.next := q2Head;
 q1Tail := q2Tail;
 end;
 end;
 procedure pr_DigitalSorting(var qHead, qTail:PInf);{Процедура цифровой сортировки очереди}
 const
 l= 2; {Количество байт для сравнения}
 mm= 10; {Количество очередей}
 var
 qmHead: array[0..mm - 1] of PInf; {Головы очередей}
 qmTail: array[0..mm - 1] of PInf; {Хвосты очередей}
 i,d,j:Integer;
 p,pTmp:PInf;
 begin
 c:=0;
 m:=0;
 for j:=l downto 1 do begin
 for i:=0 to mm-1 do {Делаем очереди пустыми}
 EmptyQueue(qmHead[i], qmTail[i]);
 p:=qHead;
 while p<>nil do begin {Заполняем очереди}
 d:=Digit(p^.num, l, j);
 pTmp:=p;
 p:=p^.next;
 SetQueueNext(qmHead[d], qmTail[d], pTmp);
 qmTail[d]^.next:=nil;
 Inc(m);
 end;
 EmptyQueue(qHead, qTail);
 for i:=0 to mm-1 do begin { Объединяем все очереди в одну }
 ConcatQueues(qHead, qTail, qmHead[i], qmTail[i]);
 Inc(m);
 end;
 end;
 end;
 procedure PrintQueue(qHead, qTail:PInf);{Процедура вывода очереди на экран и в файл}
 var
 p:PInf;
 begin
 p:=qHead;
 while p<>nil do begin
 Write(p^.num,' ');
 write(ftext, p^.num,' ');
 p:=p^.next;
 end;
 Writeln;
 writeln(ftext);
 end;
 procedure PrintInf;{Процедура вывода на экран количества операций сравнения и пересылок}
 begin
 Writeln('C = ', c, ', M = ', m);
 writeln(ftext, 'C = ', c, ', M = ', m);
 end;
 procedure Print(var qHead, qTail:PInf; s:String; keys:integer);{Процедура вывода на экран информации об очереди}
 begin
 Writeln(s,':');
 writeln(ftext, s,':');
 PrintQueue(qHead, qTail);
 Writeln;
 writeln(ftext);
 case keys of {Запуск процедуры сортировки масива взависимости от выбора в меню}
 1:pr_DirectFusion(qHead, qTail);
 2:pr_DigitalSorting(qHead, qTail);
 end;
 Writeln('Последовательность после сортировки:');
 writeln(ftext,'Последовательность после сортировки:');
 PrintQueue(qHead, qTail);
 Writeln;
 writeln(ftext);
 PrintInf;
 Writeln('Для продолжения нажмите любую клавишу...');
 ReadKey;
 end;
 var
 qHead,qTail:PInf; {Указатели на начало и конец очереди }
 begin
 ClrScr;
 Writeln('Меню выбора метода сортировки последовательности целых чисел:');
 Writeln('1. Метод прямого слияния');
 Writeln('2. Методом цифровой сортировки');
 Write('Нажмите клавишу 1, 2');
 repeat
 key:=readkey;
 until (key in chis);
 keys:=integer(key)-48;
 str(keys:1,txt_filename);
 txt_filename:='lab3' + txt_filename + '.txt';
 assign(ftext, txt_filename); {Создаем текстовый файл lab1+метод.txt}
 {$I-}Reset(ftext);{$I+} {Ловим ошибку при отсутствии файла}
 
 if IOResult = 2 then begin
 Rewrite(ftext);{Если нет файла, создаем}
 end
 else begin
 Append(ftext);
 end;
 case keys of
 1:writeln(ftext, 'Метод прямого слияния');
 2:writeln(ftext, 'Методом цифровой сортировки');
 end;
 ClrScr;
 Write('Введите количество элементов в последовательности:');
 Readln(kn);
 writeln(ftext, 'количество элементов в последовательности - ',kn);
 Writeln;
 RandomQueue(qHead, qTail);{Генерация элементов}
 Print(qHead, qTail, 'Случайная последовательность',keys);
 Writeln;
 writeln(ftext);
 Print(qHead, qTail, 'Упорядоченная последовательность',keys);
 close(ftext);
 Writeln('Для выхода из программы нажмите любую клавишу...');
 ReadKey;
 end.



