- •1 Линейные двусвязные списки
- •2 Основные операции над списком
- •2.1 Добавление элемента в список
- •2.2 Удаление элемента из списка
- •2.3 Вставка элемента внутри списка
- •3 СоЗдание, просмотр и уничтожение списка
- •Упражнения
- •4 Поиск элемента в списке
- •5 Перемещение элементов списка
- •Упражнения
- •6 Примеры обработки списка
- •Упражнение
- •Упражнение
- •Упражнения
- •Литература
Упражнение
Подготовить тестовые примеры и протестировать процедуру Dubl .
Пример 6.4 Удалить все элементы непустого списка с заданным значением x .
В процедуре удаления используются процедуры раздела 2.
procedure Del_x(var first, last:link; x:integer);
var p:link; {указатель на текущий элемент списка}
begin
p:=first;
while p<>nil do
if p^.inf=x then
begin
if p=first then {удаление первого элемента}
begin Del_first(first, last);
p:=first {указатель p перемещается на начало списка}
end
else
if p=last then {удаление последнего элемента}
begin Del_last(first, last);
p:=last {указатель p перемещается на конец списка}
end
else Del_p_next(p) {удаление текущего элемента}
end
else p:=p^.next;
end;
Контрольные примеры
1) Список (значения информационных полей списка): 1 3 7 1 3 5 1
а) x =1
Результат:
просмотр от первого до последнего элемента : 3 7 3 5
просмотр в обратном порядке : 5 3 7 3
б) x =2
Результат:
просмотр от первого до последнего элемента : 1 3 7 1 3 5 1
просмотр в обратном порядке : 1 5 3 1 7 3 1
2) Список из одинаковых элементов: 1 1 1 1
x =1
Результат просмотров от первого до последнего элемента и в обратном порядке – пустой список.
Пример 6.5 В каждой подпоследовательности из подряд идущих одинаковых элементов оставить один элемент (удалить дубликаты).
В процедуре удаления дубликатов используются процедура Del_last удаления последнего элемента (см. раздел 2 ) и процедура Del_next удаления внутреннего элемента, следующего за элементом с заданным адресом p .
Удаление элемента после элемента с заданным адресом
procedure Del_next(var p: link);
begin
p^.next:=p^.next^.next;
dispose(p^.next^.prev);
p^.next^.prev:=p
end;
Удаление дубликатов
procedure Del_dubl(first:link; var last:link);
begin
while first <> last do {цикл до последнего элемента}
if first^.inf = first^.next^.inf then
if first^.next=last then {удаление последнего элемента}
Del_last(first, last)
else {удаление элемента внутри списка}
Del_next(first)
else first:=first^.next;
end;
Контрольные примеры
1) Список (значения информационных полей списка): 1 1 1 2 3 3 5 5 5
Результат:
просмотр от первого до последнего элемента : 1 2 3 5
просмотр в обратном порядке : 5 3 2 1
2) Список из одинаковых элементов: 1 1 1 1
Результат просмотров от первого до последнего элемента и в обратном порядке – список из одного элемента со значением информационного поля равным 1.
Упражнение
Описать процедуру удаления дубликатов, не использующую процедуру Del_last удаления последнего элемента. Сравнить тексты и работу обеих процедур удаления дубликатов.
Пример 6.6 Удалить из списка перед первым элементом с заданным значением x один элемент, если значение удаляемого элемента отрицательно.
Если удаление невозможно, указать причину.
Алгоритм удаления элемента
Удаление невозможно,
если список пуст, или состоит из одного элемента,
или элемент с заданным значением x – первый в списке.
Если второй элемент списка имеет заданное значение x,
а значение первого элемента отрицательно, то удаляется первый элемент,
иначе организуется поиск пары элементов:
один из элементов имеет заданное значение x,
а элемент, предшествующий ему, – отрицательное значение.
Если такая пара элементов найдена, то первый элемент из этой пары (с отрицательным значением) удаляется.
Процедура Del_prev_minus решения задачи использует для удаления внутреннего элемента, предшествующего элементу с заданным адресом p, процедуру Del_prev.
Удаление элемента перед элементом с заданным адресом
procedure Del_prev(p: link);
begin
p^.prev:=p^.prev^.prev;
dispose(p^.prev^.next);
p^.prev^.next:=p
end;
procedure Del_prev_minus(var first:link; last:link;
x:integer);
var p:link; fl: boolean;
begin
if (first=nil) and (last=nil) then
writeln('список пуст')
else
if (first^.next=nil) and (first^.prev=nil) then
writeln('в списке один элемент')
else
if first^.inf=x then
writeln('элемент с заданным значением – первый')
else
begin
p:=first^.next;
if (p^.inf=x) and (first^.inf < 0) then
begin {удаление первого элемента списка}
p^.prev:=nil;
dispose(first);
first:=p
end
else
begin
fl:=true;
while (p<>nil)and fl do {поиск пары элементов}
if (p^.inf=x) and (p^.prev^.inf < 0)
then fl:= false
else p:=p^.next;
if fl then
writeln('элемент с заданным значением не найден ',
'или перед ним неотрицательный элемент')
else {пара элементов найдена}
Del_prev(p) {первый элемент из пары элементов удален}
end
end
end;
Контрольные примеры (тесты)
Нормальные тесты (пара элементов, удовлетворяющих условию, найдена, и первый из элементов этой пары удалён):
1) Список (значения информационных полей списка): -1 3 1 -7 1 0 -5 1 -4 2
а) x = 3
Результат:
просмотр от первого до последнего элемента : 3 1 -7 1 0 -5 1 -4 2
просмотр в обратном порядке : 2 -4 1 -5 0 1 -7 1 3
б) x = 1
Результат:
просмотр от первого до последнего элемента : -1 3 1 1 0 -5 1 -4 2
просмотр в обратном порядке : 2 -4 1 -5 0 1 1 3 -1
2) Список из двух элементов: -3 -1
x = -1
Результат просмотров от первого до последнего элемента и в обратном порядке – список из одного элемента со значением информационного поля равным -1.
Исключительные ситуации (удаление невозможно):
1) Пустой список.
2) В списке один элемент.
3) Список: -1 3 7 -1 0 7 1 7 -4 5
а) x = -1 Элемент с заданным значением – первый в списке.
б) x = 4 Элемент с заданным значением в списке отсутствует.
в) x = 7 Каждому элементу с заданным значением предшествует элемент с неотрицательным значением (положительным или нулевым).