Автор статьи
Валерия
Эксперт по сдаче вступительных испытаний в ВУЗах
- Определяем некоторую вспомогательную ссылку на текущий элемент списка и определяем ее значение как ссылку на первый элемент.
- Если вспомогательная ссылка не указывает ни на какой элемент, то завершение алгоритма.
- Выполнение требуемой обработки элемента, на который указывает вспомогательная ссылка.
- Выбираем из элемента, на который указывает вспомогательная ссылка, ссылку на следующий элемент, и помещаем ее во вспомогательную ссылку.
- Определяем значение счетчика количества элементов равным нолю.
- Используя алгоритм прохода по списку, при выборе каждого нового элемента увеличиваем значение счетчика на единицу.
- По завершению прохода по списку счетчик содержит искомую величину.
- имеется новый элемент, у которого заполнена информационная область;
- содержимое указателя PNext в области связи равно nil;
- новый элемент определен указателем, хранимым в переменной PNew. Включение элемента в начало списка
- Если список пустой, то занести ссылку на новый элемент в указатель на начало списка. Завершить алгоритм.
- Занести в новый элемент ссылку на текущий первый элемент, взяв ее из указателя на начало списка.
- Занести в указатель на начало списка ссылку на новый элемент. Завершить алгоритм. Приведем программную реализацию этого алгоритма.
- Если список пустой, то занести ссылку на новый элемент в указатель на начало списка. Завершить алгоритм.
- Найти последний элемент списка.
- В область связи текущего последнего элемента списка со следующим внести ссылку на новый элемент.
- В область связи нового элемента с предыдущим внести ссылку на текущий последний элемент. Программная реализация алгоритма может выглядеть следующим образом:
- вставка в начало списка;
- вставка в середину списка;
- вставка в конец списка.
- список двунаправленный;
- список однонаправленный.
Алгоритм можно сформулировать следующим образом:
- В новом элементе: a. в ссылку на предыдущий элемент занести ссылку на предыдущий элемент, взятую из текущего элемента; b. в ссылку на последующий элемент занести ссылку на текущий элемент.
- В предыдущем элементе в качестве следующего занести ссылку на новый элемент.
- В текущем элементе в качестве ссылки на предыдущий занести ссылку на новый элемент.
Программная реализация алгоритма может выглядеть следующим образом:
procedureInsertBeforPCur(PList, PNewEl, PCur:PTEl);
begin
PNewEl.PNext := PCur;
PNewEl.PPrev := PCur.PPrev;
(PCur.PPrev).PNext := PNewEl;
PCur.PPrev := PNewEl;
end;
В случае однонаправленного списка сложность решения поставленной задачи определяется тем, что у нас не имеется ссылки на предыдущий относительно PCur элемент. Можно, конечно, применить достаточно традиционный подход: при проходе по списку сохранять в специально зарезервированной переменной ссылку на предыдущий элемент. Тогда решение поставленной задачи очевидно. Но при таком подходе придется использовать относительно сложный алгоритм. В этом вы можете убедиться самостоятельно.
Существует гораздо более элегантное решение проблемы средствами следующего алгоритма:
- Вставить новый элемент после (а не перед, как требуется) элемента PCur. В этом случае, у нас есть вся необходимая для этого информация. Для выполнения этого необходимо: 1.1. Занести в новый элемент ссылку на следующий за PCur, взяв ее из PCur. 1.2. Занести в элемент PCur ссылку на новый элемент.
- Теперь мы получили список, который отличается от упорядоченного тем, что у него переставлены местами элементы PCurи новый элемент. Следующее действие как раз и представляет изюминку алгоритма. 2.1. Поменяем местами информационные области элемента PCurи нового элемента. Это не составляет труда, т.к. мы имеем ссылки на оба элемента.
Итак, приведем программную реализацию вставки нового элемента в упорядоченный по возрастанию список.
ProcedureIsertElemetToList(PList, PNew : PTEL); varPCur :PTEl; begin// Проверка на то, что список не пустой
ifPList=nil then begin // Списокпустой.
AddToBegining(PList, PNew); exit; // Завершениеалгоритма.
end;// Поиск места включения нового элемента в список
PCur := PList; // Помещение в PСur указателя на первый элемент
whilePCur<>nildo // Проход по списку и поиск места вставки
beginifPNew.Key>PCur.KeythenPCur := PCur.PNext // Следующий элемент
elsebegin// надо вставлять в середину
PNew.PNext := PCur.PNext; PCur.PNext := PNew; // Обмен информационных полей PCurи PNew.
exit; // Завершение алгоритма.
end;
end;// Новый элемент требуется включить в конец списка.
AddToEnd(PList, PNew); end;
Конкатенация (объединение) двух списков
Алгоритм объединения двух списков основывается, практически, на двух рассмотренных выше алгоритмах: алгоритме прохода по списку и алгоритму добавления элемента в конец списка.
Пусть у нас есть список 1 и список 2. Необходимо к списку 1 присоединить список 2. Рассматриваемый алгоритм можно сформулировать следующим образом:
1. Если список 1 пустой, то занести ссылку на первый элемент списка 2 в указатель списка 1. Завершить алгоритм.
2. Если список 2 пустой, то завершить алгоритм.
3. Используя алгоритм прохода по списку найти последний элемент в списке 1.
4. Использовать алгоритм включения элемента в конец списка 1. В качестве включаемого списка выбрать ссылку на первый элемент списка 2 из указателя на начало списка 2.
5. Если необходимо присвоить указателю на начало списка 2 значение nil.
Программная реализация данного алгоритма может выглядеть следующим образом:
Procedure ConcatLists(var PList1,PList2 :PTEl);
varPCur : PTEl;
begin
if PList1=nil then
begin
PList1 := PList2;
PList2 := nil;
exit;
end;
if PList2=nil then exit;
PCur := PList1;
while PCur.PNext<>nil do PCur := PCur.PNext;
AddToEnd(PList1, PCur);
PList2 := nil;
end;
Удаление элемента
Характерной особенностью при удалении элемента является то, что не достаточно просто исключить элемент из списка. Необходимо освободить память, зарезервированную для хранения этого элемента. Иначе, в общем случае, теряется сама возможность доступа к этому участку памяти, этот участок памяти остается захваченным и не сможет больше использоваться до завершения программы.
При удалении элемента из линейного списка необходимо также как и при добавлении элемента учитывать относительное положение удаляемого элемента.
Удаление элемента из начала списка
При удалении элемента из начала списка необходимо в указатель на начало списка занести ссылку на элемент, следующий за первым и освободить память, отведенную для хранения удаляемого элемента.
Алгоритм удаления элемента из начала списка выглядит следующим образом:
1. Если список пустой, то завершить алгоритм.
2. Выбрать из первого элемента ссылку на следующий и занести ее в указатель на начало списка.
3. Освободить память, зарезервированную под элемент, бывший первым.
Приведем программную реализацию этого алгоритма.
procedureDeleteOfBegining(varPList:PTEl);
var PCur : PTEl;
begin
ifPList=nil then exit;
PCur :=PList;
PList :=PCur.PNext;
FreeMem(PCur);
end;
Следует обратить внимание на то, что если список состоит из одного элемента, то приведенный алгоритм корректен. Действительно, в этом случае ссылка из первого (и единственного) элемента на следующий содержит указание на то, что дальнейших элементов в списке нет.
И именно эта ссылка помещается в указатель на начало списка. Следовательно, указатель на начало списка будет содержать указание на то, что дальнейших элементов в списке нет. А это и есть свидетельство факта, что список стал пустой.
Удаление последнего элемента списка.
Алгоритм удаления последнего элемента из двухсвязного списка не содержит никаких новых особенностей и поэтому нет смысла останавливаться на нем подробно. Немногим более сложен алгоритм удаления последнего элемента списка в случае односвязного списка. Особенность его состоит в том что, перебирая элементы последовательно, при достижении последнего элемента у нас отсутствует ссылка на предыдущий, который теперь должен стать последним.
Существуют различные подходы к решению этой проблемы, но все из них основаны на том, чтобы тем или иным образом существовали ссылки на два последовательно расположенных элемента списка.
Наиболее популярный среди начинающих является алгоритм, базирующийся на непосредственном сохранении ссылки на предыдущий элемент. Его недостаток в том, что в этом случае для первого элемента не существует предыдущего элемента и поэтому в алгоритм необходимо вводить особую обработку первого элемента, что, естественно, усложняет алгоритм.
Приведем алгоритм лишенный указанного недостатка и основанный не на запоминании предыдущего элемента, а наоборот на «заглядывании» вперед на следующий элемент.
- Если список пустой, то завершить алгоритм.
- Выбрать первый элемент в качестве текущего элемента.
- Проверить ссылку в следующем элементе на то, что он не последний. 3.1. Если это не последний элемент, то выбрать в качестве текущего следующий элемент и перейти к пункту 3. 3.2. Если этот элемент последний, то: 3.2.1. Освободить память, занимаемую последним элементом. 3.2.2. Занести в ссылку текущего элемента на следующий признак окончания списка.
- Если список пустой, то завершить алгоритм.
- Выбрать первый элемент в качестве текущего элемента.
- Сравнить значение заданного ключа с ключом текущего (первого) элемента. 3.1. Если значения ключей совпадают, то удалить текущий элемент в соответствии с алгоритмом удаления первого элемента. 3.2. Завершить работу алгоритма.
- Если значения ключей не совпадают проверить, не является ли текущий элемент последним. 4.1. Если текущий элемент последний, то искомый элемент отсутствует в списке. 4.2. Завершить работу алгоритма.
- Если текущий элемент не последний, сравнить значение ключа элемента следующего за текущим с заданным. 5.1. Если значения совпадают, то следующий элемент должен быть удален. Занести в текущий элемент в качестве ссылки на следующий ссылку, хранимую в следующем элементе. 5.2. Освободить зарезервированную память под следующий элемент. 5.3. Завершить работу алгоритма.
- Выбрать следующий элемент в качестве текущего элемента. Перейти к пункту 4.
- Используя алгоритм прохода по списку найти третий элемент.
- Используя алгоритм удаления первого элемента удалить пять элементов.
- Используя алгоритм прохода по списку найти граничный элемент, являющийся последним для первого списка.
- Занести в указатель на начало второго списка ссылку на элемент, следующий за граничным элементом.
- Удалить ссылку на следующий элемент в граничном элементе.
О сайте
Ссылка на первоисточник:
http://miit-ief.ru
Поделитесь в соцсетях: