Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Poyasnitelnaya_zapiska_RED.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.36 Mб
Скачать

3 Логические структуры данных

Основная структура данных проекта – линейный двусвязный список. Атрибутами элементов списка являются имя, фамилия и отчество члена ВТК, год рождения, код ХД, сумма вознаграждения и горо, где находится отделение банка. Кроме того, каждый элемент списка содержит два указателя, один из которых, прямой указатель (direct pointer), адресует следующий справа элемент, а другой, обратный указатель (backward pointer), адресует предыдущий элемент списка.

Ниже представлено описание элемента списка.

Type

TPointer = ^TListStore;

TListStore=record

Name: string[50];//имя

FamilyName:string[50];//фамилия

Patronymic:string[50];//отчество

Year:integer;//год рождения

Kod:string[10];//код ХД

SummMany:extended;//вознаграждение

City:string[100];//город

Dir,Back:TPointer;//указатели

end;

Начало и конец такого списка эквивалентны, так как доступ к элементу может быть осуществлен с любого конца. Поэтому вместо терминов «начало» и «конец» списка используют термины «левый конец» и «правый конец». Соответственно называются и указатели:

Var

Left, Right, Current, G, Sort:TPointer;

Логическая структура списка:

Name

FamilyName

Patronymic

Year

Kod

SummMany

City

Dir

Back

4 Алгоритмы обработки основных структур

Вся работа со списком определена в классе TNoFreeXD. Ниже рассмотрены все его процедуры (операции над списком).

TNoFreeXD=class(TObject)

private

Left{начало}, Right{конец}, Current, G, Sort{для сортировки}:TPointer;

procedure ElementToStringGrid(i:Cardinal;StringGrid:TStringGrid);

public

procedure FormingList;

procedure GetList(StringGrid:TStringGrid);

procedure ClearList;

procedure Sorting(Index:Integer;Increase:Boolean);

procedure Replace;

procedure Search(Index:Integer;Text:String;StringGrid:TStringGrid);

end;

1. Формирование линейного двусвязного списка членов незавершенных ХД.

Производится просмотр всех членов ВТК. Если член ВТК связан с ХД который не завершен, то он заносится в список (заполняются соответствующие поля элемента списка).

procedure TNoFreeXD.FormingList;

var

i,j,k:Cardinal;

str,_strYear:string;

Year: Word;

Month: Word;

Day: Word;

begin

ClearList;

New(Current);

Left:=Current;//указатель на начало

Current^.Back:=nil;//указатель на предыдущий должен равен быть в начале (nil)

for i:=0 to GetBTKM-1 do

begin

for j:=0 to GetXDM-1 do

begin

DecodeDate(XD[j].DateCreat,Year,Month,Day);

_strYear:=IntToStr(Year);

str:=IntToStr(XD[j].Number)+'/'+_strYear[3]+_strYear[4];

if (str=BTK[i].Kod) and (XD[j].PriznakFree=false) then

begin

Current^.Name:=BTK[i].Name;

Current^.FamilyName:=BTK[i].FamilyName;

Current^.Patronymic:=BTK[i].Patronymic;

Current^.Year:=BTK[i].Year;

Current^.Kod:=BTK[i].Kod;

Current^.SummMany:=BTK[i].SummMany;

for k:=0 to GetBANKM-1 do

begin

if BANK[k].Number=BTK[k].NumberBank then

begin

Current^.City:=BANK[i].City;

end;

end;

New(Current^.Dir);

Current^.Dir^.Back:= Current;//указатель на данный элемент

Current:=Current^.Dir;//указатель на следующий

end;

end;

end;

Current^.Back^.Dir:=nil;

Right:=Current^.Back;//указатель на конец списка(равен предыдущему)

Dispose(Current);

end;

Логические схемы операции формирования списка.

После выполнения операторов

New(Current); Left:=Current; Current^.Back:=nil;

После нахождения первого члена ВТК.

После завершения просмотра.

После выполнения операторов

Current^.Back^.Dir:=nil; Right:=Current^.Back; Dispose(Current);

2. Просмотр списка и его отображение в таблице StringGrid.

Сначала производится очистка таблицы, а затем последовательный просмотр элементов списка, начиная с левого конца.

procedure TNoFreeXD.GetList(StringGrid:TStringGrid);

var

i,j:integer;

begin

for i:=1 to 25 do

for j:=0 to 8 do

StringGrid.Cells[j,i]:='';

Current:=Left;//получаем указатель на начало

i:=1;

while Current<> nil do

begin

StringGrid.Cells[0,i]:=IntToStr(i);

StringGrid.Cells[1,i]:=Current^.Name;

StringGrid.Cells[2,i]:=Current^.FamilyName;

StringGrid.Cells[3,i]:=Current^.Patronymic;

StringGrid.Cells[4,i]:=IntToStr(Current^.Year);

StringGrid.Cells[5,i]:=Current^.Kod;

StringGrid.Cells[6,i]:=FloatToStr(Current^.SummMany);

StringGrid.Cells[7,i]:=Current^.City;

Current:=Current^.Dir;//указатель на следующий элемент

Inc(i);

end;

end;

3. Поиск элементов по заданному атрибуту в списке

Пользователь задает атрибут поиска и его значение. В процедуре Search производится последовательный просмотр элементов списка в направлении от левого конца к правому. Если элемент удовлетворяет искомому значению, то он помещается в таблицу. По завершении поиска появляется сообщение о количестве найденных элементов.

Procedure TNoFreeXD.Search(Index:Integer;Text:String;StringGrid :TStringGrid);

var i, j:integer;

begin

for i:=1 to 250 do

for j:=0 to 5 do

StringGrid.Cells[j,i]:='';

Current:=Left;//получаем указатель на начало

i:=1;

while Current<> nil do

begin

case Index of

0: if Current^.Name=Text

then

begin

ElementToStringGrid(i,StringGrid);

Inc(i);

end;

1: if Current^.FamilyName=Text

then

begin

ElementToStringGrid(i,StringGrid);

Inc(i);

end;

2: if Current^.Patronymic=Text

then

begin

ElementToStringGrid(i,StringGrid);

Inc(i);

end;

3: if Current^.Year=StrToInt(Text)

then

begin

ElementToStringGrid(i,StringGrid);

Inc(i);

end;

4: if Current^.SummMany=StrToFloat(Text)

then

begin

ElementToStringGrid(i,StringGrid);

Inc(i);

end;

5: if Current^.City=Text

then

begin

ElementToStringGrid(i,StringGrid);

Inc(i);

end;

end;

Current:=Current^.Dir;

end;

MessageDlg('Поиск завершен. Найдено элементов - '+IntToStr(i-1),mtInformation,[mbOk],0);

end;

procedure TNoFreeXD.ElementToStringGrid(i:Cardinal;StringGrid :TStringGrid);

begin

StringGrid.Cells[0,i]:=IntToStr(i);

StringGrid.Cells[1,i]:=Current^.Name;

StringGrid.Cells[2,i]:=Current^.FamilyName;

StringGrid.Cells[3,i]:=Current^.Patronymic;

StringGrid.Cells[4,i]:=IntToStr(Current^.Year);

StringGrid.Cells[5,i]:=Current^.Kod;

StringGrid.Cells[6,i]:=FloatToStr(Current^.SummMany);

StringGrid.Cells[7,i]:=Current^.City;

end;

4. Сортировка списка прямым выбором

Пользователь выбирает способ упорядочения и атрибут сортировки списка.

Алгоритм этого метода сортировки следующий.

Выбирается (выделяется) элемент с наименьшим (или наибольшим – в зависимости от способа упорядочения: по возрастанию, по убыванию) значением атрибута сортировки. Затем этот элемент меняется местом с первым элементом списка. Среди остальных элементов списка (т.е. среди всех кроме первого) снова выбирается элемент с наименьшим значением атрибута сортировки. Он меняется местом со вторым элементом списка. Далее все повторяется, пока не останется один наибольший элемент списка.

procedure TNoFreeXD.Sorting(Index:Integer;Increase:Boolean);

var

XPointer:TPointer;

begin

if Left=Right then Exit;

XPointer:=Left;

while XPointer^.Dir<>nil do

begin

Sort:=XPointer;//берем указатель на элемен

XPointer:=XPointer^.Dir;//перемещаемм указатель на следующий

G:=Sort;//элемент с которым будем сравнивать

Current:=G^.Dir;//следующий элемент

while Current<>nil do//пока не пройдем весь список

begin

case Index of

0: if Increase=True//как сортировать(убыванию или увелечению)

then

begin

if G^.Name<Current^.Name

then G:=Current;

end

else if G^.Name>Current^.Name

then G:=Current;

1: if Increase=True

then

begin

if G^.FamilyName<Current^.FamilyName

then G:=Current;

end

else if G^.FamilyName>Current^.FamilyName

then G:=Current;

2: if Increase=True

then

begin

if G^.Patronymic<Current^.Patronymic

then G:=Current;

end

else if G^.Patronymic>Current^.Patronymic

then G:=Current;

3: if Increase=True

then

begin

if G^.SummMany<Current^.SummMany

then G:=Current;

end

else if G^.SummMany>Current^.SummMany

then G:=Current;

4: if Increase=True

then

begin

if G^.City<Current^.City

then G:=Current;

end

else if G^.City>Current^.City

then G:=Current;

5: if Increase=True

then

begin

if G^.Year<Current^.Year

then G:=Current;

end

else if G^.Year>Current^.Year

then G:=Current;

end;

Current:=Current^.Dir;//указываем на следующий элемент

end;

//если было изменение(одно из if сработало) то меняем указатели

if G<>Sort then Replace;

end;

end;

procedure TNoFreeXD.Replace;

begin

if G^.Dir<>nil

then G^.Dir^.Back:=Sort

else Right:=Sort;

if Sort^.Dir<>G

then

begin

Sort^.Dir^.Back:=G;

G^.Back^.Dir:=Sort;

end;

if Sort^.Back<>nil

then Sort^.Back^.Dir:=G

else Left:=G;

Current:=G^.Dir;

if Sort^.Dir=G

then G^.Dir:=Sort

else G^.Dir:=Sort^.Dir;

Sort^.Dir:=Current;

if G^.Back=Sort

then

begin

Current:=Sort^.Back;

Sort^.Back:=G;

G^.Back:=Current;

end

else

begin

Current:=G^.Back;

G^.Back:=Sort^.Back;

Sort^.Back:=Current;

end;

end;

Логические схемы операции сортировки

Рассмотрим один из шагов сортировки списка по возрастанию года рождения (первый шаг).

Стартовая структура (часть линейного двусвязного списка). Указатель G ссылается уже на элемент с минимальным значением атрибута. Требуется поменять местами первый элемент, на который указывает Sort, и элемент, на который указывает G.

После выполнения G^.Dir^.Back:=Sort

После выполнения Sort^.Dir^.Back:=G; G^.Back^.Dir:=Sort;

После выполнения Left:=G; Current:=G^.Dir;

После выполнения G^.Dir:=Sort^.Dir; Sort^.Dir:=Current;

После выполнения

Current:=G^.Back; G^.Back:=Sort^.Back; Sort^.Back:=Current;

Преобразование к более привычному виду двусвязного списка.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]