Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Бабалова Алгоритмизация задач и структурирование программ 2013

.pdf
Скачиваний:
2
Добавлен:
12.11.2022
Размер:
1.29 Mб
Скачать

Stack – название стека, PStack – указатель на стек, Item – элемент стека и Next – указатель на следующий элемент стека.

Двусвязный список: Type

PLine=^Line;

Line=record

Item:PString;

Prev,Next:PLine;

end;

Line – название очереди, PLine – указатель на очередь, Item – элемент очереди, Prev – указатель на предыдущий элемент очереди, Next – указатель на следующий элемент очереди.

Кольцевой список представляет собой список, конец которого замкнут на начало. Указатель последнего элемента списка должен ссылаться на начало списка. Формирование списка – это, прежде всего, выделение памяти из кучи (Heap) для записи списочных элементов. Стандартные процедуры для работы со списочными структурами: New(List) выделение адреса в куче для элемента списка. Dispose(List) уничтожение адреса одного элемента списка.

Пример 5.1. Создать список сотрудников некоторой организации и найти среди них однофамильцев.

Решение задачи начинается с создания списков сотрудников. Исходные данные сохраним в файле. Для поиска однофамильцев выполним сортировку списочной структуры данных и найдем всех однофамильцев. На рис. 28 приведена структура программы. Все виды работ предлагается перечислить в меню. Создание списка возможно только тогда, когда сформирован файл с требуемыми данными. Поиск однофамильцев осуществляется только после сортировки созданного списка данных. Все действия, обозначенные в меню, оформляются процедурами или функциями.

В структуре программы есть метод «Создание списка». На рис. 29 изображен использованный в примере решения этой задачи алгоритм создания односвязного списка типа очереди.

Алгоритм поиска однофамильцев Seach_double разработан для отсортированного списка. В этом случае поиск одинаковых записей существенно упрощается. Алгоритм поиска однофамильцев приведен на рис. 30.

71

Рис. 28. Структура программы для обработки списков

Рис. 29. Алгоритм создания списка типа очереди

72

Рис. 30. Алгоритм поиска однофамильцев в списке

Валгоритме поиска есть два цикла для движения по списку. Внутренний цикл собственно выявляет однофамильцев. А внешний цикл обеспечивает движение по списку для выбора следующей фамилии. Логическая переменная v контролирует выбор однофамильца. Переменная i определяет количество найденных однофамильцев. Процедура, описывающая этот алгоритм, имеет в программе аналогичное имя.

Валгоритме выделены два важных момента – это сохранение начала списка в переменной lb и обозначение конца списка – переменная lk.

Программа: program ProjectList_rec; {$APPTYPE CONSOLE} uses

SysUtils,Windows; //Для работы со строками пришлось добавить

// модуль среды Windows, содержащий методы обработки строк.

73

const a:array[1..6]of string[30]=( '1.Создать файл', '2. Создать список ', '3. Вывод списка ',

'4. Сортировать список', '5. Найти однофамильцев ', '6. Выход') ;

Type str=string[30]; D_d=record

Title:str;

Fnm,Secnm:str;

Number:word;

end;

//Структура данных представлена как запись

//из полей фамилии, имени, отчества и

//некоторого номера сотрудника

ff=file of D_d;

//Типизированный файл из записей

Plist=^List;

List=record

lis:D_d; // Информационное поле списка next:Plist;

end; // Списочная структура данных var n,i:integer;

ch:char;

f1:ff;

pn,Pstart:Plist;

// Необходимые глобальные переменные function ToRus(winStr:String):string; begin

setlength(Result,Length(WinStr));

CharToOEM(PChar(WinStr),PChar(Result));

end;

//Эта функция нужна только для консольного

//приложения. Вы ее просто копируете в

//каждую новую свою программу, если

//хотите видеть комментарии на русском языке. procedure save_data_file(var f:ff);

74

// Процедура для сохранения данных в файле var ld:d_d;

begin

writeln(ToRus('******Введите исходные данные')); repeat

with ld do begin

write(ToRus('Фамилия ')); readln(Title); write(ToRus('Имя ')); readln(Fnm); write(ToRus('Отчество ')); readln(Secnm); write(ToRus('Номер ')); readln(number);

end;

write(f,ld); writeln(ToRus('******Есть еще сведения? '));

readln(ch); until ch ='n'; closefile(f);

writeln(ToRus('******Данные сохранены в файле*** ')); readln;

end;

procedure Insert_list(Var pp:pList;el:D_d); // Процедура для вставки элемента в список

Var ls,lp: pList; begin

if pp=nil then begin new(lp);

with lp^ do begin lis:=el; next:=nil; end; pp:=lp;

// Запоминаем начало списка

75

end else begin

new(ls);

lp^.next:=ls; with ls^ do

begin lis:=el; next:=nil;

end;

lp:=ls;

// Обеспечиваем движение по списку end;

end;

procedure List_Create(var pp:plist);

// Процедура создания списка из данных, сохраненных в файле var d:D_d;

begin

While not eof(f1) do begin

read(f1,d); Insert_list(pp,d); end;

closefile(f1);

end;

//Вывод созданного списка procedure List_Output(var pp:plist);

var lp:plist; i:integer;

begin lp:=pp; i:=1;

while lp<>nil do begin

write(i, '---'); with lp^ do

begin write(lis.Title,' + '); write(lis.Fnm,' + ');

76

write(lis.secnm,' + '); writeln(lis.number);

end;

lp:=lp^.next;

i:=i+1;

end;

end;

procedure Sort_list(var pp:Plist); // Сортировка списка по фамилиям

var p1,p2:plist; tt:D_d; nowswap:boolean;

begin Repeat

p1:=pp;

p2:=p1^.next;

nowswap:=true; while(p2<>nil) do

begin

if (p1^.lis.Title>p2^.lis.Title) then begin

nowswap:=false; tt:= p1^.lis; p1^.lis:= p2^.lis; p2^.lis:=tt;

//Для сортировки списка достаточно

//переставить только поля данных

end;

p1:=p2;

p2:=p2^.next;

end;

Until nowswap; end;

procedure Seach_double(var pp:Plist); // Процедура поиска однофамильцев

var i:integer; v:boolean;

77

lp,ls:plist; begin

lp:=pp;

ls:=lp;

i:=1;

while lp<> nil do begin

v:=true ;

while (v and(ls<>nil)) do begin

if ls<>lp then

if lp^.lis.Title =ls^.lis.Title then begin

write(i,' '); write(lp^.lis.Title+' '); write(lp^.lis.Fnm +' '); write(lp^.lis.Secnm +' '); write(lp^.lis.number); writeln;

i:=i+1;

v:=false;

end;

ls:= ls^.next; end;

ls:=lp;

lp:=lp^.next;

end;

If i=1 Then

writeln (ToRus('*****Однофамильцев нет****'));

end;

begin // Основная программа с меню работ writeln(ToRus('*****начало работы****'));

Assignfile(f1,'Wind.dat');

pn:=nil;

For i:=1 to 6 do writeln(ToRus(a[i]):40);

// Вывод на экран меню

78

Repeat

writeln(ToRus('*****Введите номер выполняемого дейст-

вия****'));

readln(n); case n of

1: begin

writeln(ToRus('*****Файл надо создать****'));

rewrite(f1); save_data_file(f1); end;

2: begin Pstart:=Init(pn); reset(f1);

Writeln(ToRus('*****Создание списка****' )); list_create(Pstart);

end; 3: begin

writeln (ToRus('*****Вывод списка****'));

List_Output(Pstart);

end; 4: begin

writeln (ToRus('*****Сортировка списка****'));

Sort_list(Pstart); List_Output(Pstart); readln;

end; 5: begin

writeln (ToRus('*****Поиск однофамильцев****'));

Seach_double(PStart); readln;

end; 6: Halt; end;

Until false;

{ TODO -oUser -cConsole Main : Insert code here }

end.

79

Экран с решением задачи показан на рис. 31.

Рис. 31. Решение задачи по поиску однофамильцев

Виллюстрации решения задачи отражены все действия со списком: создание списка, сортировка списка по алфавиту и поиск однофамильцев в созданном списке.

Рассмотрим решение задачи со списочной структурой с использованием визуальных компонент среды Delphi.

Пример 5.2. Игроки имеют свои номера. Выпадает случайное число. Это число определяет игрока, который выбывает из игры. Побеждает тот игрок, номер которого не будет назван.

Врешении задачи надо будет удалять выпавший номер игрока из списка. На рис. 31 изображен алгоритм удаления элемента из списка.

80