|
Я завершила экзамен 90 баллов на 5. Сертификат не заказала. Сейчас пытаюсь найти как его заказать. у меня указано экзамен пройден баллы оценка видно, а чтоб заказать сертификат нигде не видно. |
Работа с динамической памятью
Линейные списки
В линейном списке каждый элемент связан со следующим и, возможно, с предыдущим. В первом случае список называется односвязным, во втором — двусвязным. Также применяются термины "однонаправленный" и "двунаправленный". Если последний элемент связать указателем с первым, получится кольцевой список.
Каждый элемент списка содержит ключ, идентифицирующий этот элемент. Ключ обычно бывает либо целым числом, либо строкой и является частью поля данных. В качестве ключа в процессе работы со списком могут выступать разные части поля данных. Например, если создается линейный список из записей, содержащих фамилию, год рождения, стаж работы и пол, любая часть записи может выступать в качестве ключа. При упорядочивании списка по алфавиту ключом будет фамилия, а при поиске, например, ветеранов труда — стаж. Ключи разных элементов списка могут совпадать.
Над списками можно выполнять следующие операции:
- начальное формирование списка (создание первого элемента);
- добавление элемента в конец списка;
- чтение элемента с заданным ключом;
- вставка элемента в заданное место списка (до или после элемента с заданным ключом);
- удаление элемента с заданным ключом;
- упорядочивание списка по ключу.
Стек и очередь представляют собой частные случаи линейного списка с ограниченным набором допустимых операций.
При чтении элемент списка не удаляется, в отличие от элемента, выбираемого из стека и очереди. Для работы со списком в программе требуется определить указатель на его начало. Чтобы упростить добавление новых элементов в конец списка, можно также завести указатель на конец списка.
Рассмотрим программу ( пример 5.3), которая формирует односвязный список из пяти элементов, содержащих число и его текстовое представление, а затем выполняет вставку и удаление заданного элемента. В качестве ключа используется число.
program linked_list;
const n = 5;
type pnode = ^node;
node = record { элемент списка }
d : word;
s : string;
p : pnode;
end;
var beg : pnode; { указатель на начало списка }
i, key : word;
s : string;
option : word;
const text: array [1 .. n] of string = ('one', 'two', 'three', 'four', 'five');
{ -------------- добавление элемента в конец списка --------------------------- }
procedure add(var beg : pnode; d : word; const s : string);
var p : pnode; { указатель на создаваемый элемент }
t : pnode; { указатель для просмотра списка }
begin
new(p); { создание элемента }
p^.d := d; p^.s := s; { заполнение элемента }
p^.p := nil;
if beg = nil then beg := p { список был пуст }
else begin { список не пуст }
t := beg;
while t^.p <> nil do { проход по списку до конца }
t := t^.p;
t^.p := p; { привязка нового элемента к последнему }
end
end;
{ ------------------------- поиск элемента по ключу --------------------------- }
function find(beg : pnode; key : word; var p, pp : pnode) : boolean;
begin
p := beg;
while p <> nil do begin { 1 }
if p^.d = key then begin { 2 }
find := true; exit end;
pp := p; { 3 }
p := p^.p; { 4 }
end;
find := false;
end;
{ -------------------------------- вставка элемента --------------------------- }
procedure insert(beg : pnode; key, d : word; const s : string);
var p : pnode; { указатель на создаваемый элемент }
pkey : pnode; { указатель на искомый элемент }
pp : pnode; { указатель на предыдущий элемент }
begin
if not find(beg, key, pkey, pp) then begin
writeln(' вставка не выполнена'); exit; end;
new(p); { 1 }
p^.d := d; p^.s := s; { 2 }
p^.p := pkey^.p; { 3 }
pkey^.p := p; { 4 }
end;
{ ------------------------------- удаление элемента --------------------------- }
procedure del(var beg : pnode; key : word);
var p : pnode; { указатель на удаляемый элемент }
pp : pnode; { указатель на предыдущий элемент }
begin
if not find(beg, key, p, pp) then begin
writeln(' удаление не выполнено'); exit; end;
if p = beg then beg := beg^.p { удаление первого элемента }
else pp^.p := p^.p;
dispose(p);
end;
{ ------------------------------------ вывод списка --------------------------- }
procedure print(beg : pnode);
var p : pnode; { указатель для просмотра списка }
begin
p := beg;
while p <> nil do begin { цикл по списку }
writeln(p^.d:3, p^.s); { вывод элемента }
p := p^.p { переход к следующему элементу списка }
end;
end;
{ ------------------------------- главная программа --------------------------- }
begin
for i := 1 to 5 do add(beg, i, text[i]);
while true do begin
writeln('1 - вставка, 2 - удаление, 3 - вывод, 4 - выход');
readln(option);
case option of
1: begin { вставка }
writeln('Ключ для вставки?');
readln(key);
writeln('Вставляемый элемент?');
readln(i); readln(s);
insert(beg, key, i, s);
end;
2: begin { удаление }
writeln('Ключ для удаления?');
readln(key);
del(beg, key);
end;
3: begin { вывод }
writeln('Вывод списка:');
print(beg);
end;
4: exit; { выход }
end
writeln;
end
end.
Листинг
5.3.
Использование списка
Функция поиска элемента find возвращает true, если искомый элемент найден, и false в противном случае. Поскольку одного факта отыскания элемента недостаточно, функция также возвращает через список параметров два указателя: на найденный элемент p и на предшествующий ему pp. Последний требуется при удалении элемента из списка, поскольку при этом необходимо связывать предыдущий и последующий по отношению к удаляемому элементы.
Сначала указатель p устанавливается на начало списка, и организуется цикл просмотра списка (оператор 1). Если поле данных очередного элемента совпало с заданным ключом (оператор 2), формируется признак успешного поиска и функция завершается. В противном случае перед переносом указателя на следующий элемент списка (он хранится в поле p текущего элемента, оператор 4) его значение запоминается в переменной pp (оператор 3) для того, чтобы при следующем проходе цикла в ней находился указатель на предыдущий элемент.
Если элемента с заданным ключом в списке нет, цикл завершится естественным образом, поскольку последний элемент списка содержит nil в поле p указателя на следующий элемент.
Вставка элемента выполняется после элемента с заданным ключом (процедура insert ). Если с помощью функции find место вставки определить не удалось, выводится сообщение и процедура завершается (в этом случае можно было использовать и другой алгоритм — добавлять элемент к концу списка, это определяется конкретным предназначением программы). Если элемент найден, указатель на него заносится в переменную pkey.
Под новый элемент выделяется место в динамической памяти (оператор 1), и информационные поля элемента заполняются переданными в процедуру значениями (оператор 2). Новый элемент p вставляется между элементами pkey и следующим за ним (его адрес хранится в pkey^.p ). Для этого в операторах 3 и 4 устанавливаются две связи ( рис. 5.4).
Удаление элемента выполняет процедура del. В ней две ветви, поскольку при удалении элемента из начала списка изменяется указатель на начало, а при удалении второго и последующих элементов требуется связывать предыдущий и последующий по отношению к удаляемому элементы.
