Я завершила экзамен 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. В ней две ветви, поскольку при удалении элемента из начала списка изменяется указатель на начало, а при удалении второго и последующих элементов требуется связывать предыдущий и последующий по отношению к удаляемому элементы.