Научная статья на тему 'Алгоритмы над списками'

Алгоритмы над списками Текст научной статьи по специальности «Математика»

CC BY
124
52
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ПЕРЕВОРОТ ЛИНЕЙНОГО СПИСКА / ПОСТРОЕНИЕ КОПИИ СПИСКА / ВСТАВКА В УПОРЯДОЧЕННЫЙ СПИСОК / ДИНАМИЧЕСКИЕ ДЕМОНСТРАЦИИ АЛГОРИТМОВ

Аннотация научной статьи по математике, автор научной работы — Дмитриева Марина Валерьевна

Статья продолжает цикл, начатый в № 1, 2, 2007 г. В статье рассматриваются алгоритм, демонстрирующие различные методы работы со списками: переворот линейного списка, построение копии списка, вставка в упорядоченный список элемента и удаление из списка всех элементов с заданным значением информационного поля. Проиллюстрированы новые возможности работы с указателями. На диске размещен электронный гипертекстовый учебник по работе со списками, включающий динамические демонстрации алгоритмов и тесты.

i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

Текст научной работы на тему «Алгоритмы над списками»

Дмитриева Марина Валерьевна

АЛГОРИТМЫ НАД СПИСКАМИ

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

ПЕРЕВОРОТ ЛИНЕЙНОГО СПИСКА

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

..рассмо&рим алгоритм пере&ор/ийа списка

ному списку. Рассмотрим линейный список, приведенный на рис. 1.

После преобразования (переворота) должен стать таким, как на рис. 2.

При описании алгоритма используем четыре переменные: указатель Ъ установлен на первый элемент исходного списка, указатель Ь1 установлен на текущий обрабатываемый элемент списка, указатель б -на начало уже сформированного списка, переменная р играет вспомогательную роль.

Далее необходимо установить указатель Р на текущий элемент рассматриваемого списка {1}, указатель переместить на следующий элемент исходного списка {2}, вставить элемент, на который установлен указатель р, в начало списка б {3}, и изменить указатель на начало перевернутого списка, установив его на только что обработанный элемент {4}.

Указатель установлен на первый элемент не просмотренной части линейного списка, указатель б установлен на «перевернутое» начало списка. Если просмотрен весь исходный список, то переменная б является указателем на перевернутый список. Так как требовалось перевернуть исходный список, то переменной Ъ следует присвоить значение б, и задача будет полностью решена. Процедура переворота линейного списка приведена в листинге 1.

Рис. 1. Линейный цепной список

Рис. 2. Список после переворота

• i ЕНПИНПШ-

Рис. 3. Список после переворота первых элементов

На рис. 3 изображена ситуация, когда просмотрены первые элементы списка, но список еще не исчерпан.

СОЗДАНИЕ КОПИИ СПИСКА

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

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

Листинг 1. Переворот линейного списка

procedure rev list (var t list);

var p,t1,s: list;

begin t1 := t; s := nil;

while t1 <> nil do

begin

p := t1; {1}

t1 := t1A.next; {2}

pA.next := s {3}

s := p {4}

end;

t := s

end

созданный элемент установлено два указателя р и р1 (первый и последний элемент списка копии). Указатель устанавливается на второй элемент списка, если этот элемент в списке есть. Остальные действия выполняются с помощью цикла. Процедура создания копии списка приведена в листинге 2.

Рассмотрим тело цикла. В точке программы {1} выполнен запрос на выделение памяти под очередной элемент копии. В {2} скопировали информационное поле рассматриваемого элемента. В {3} «подцепили» построенный элемент к последнему

Листинг 2. Процедура построения копии списка

procedure copy_list (var t, p: list);

var t1,p1,q: list; begin if t= nil then p := nil else

begin {список не пуст} new (p); pi := p; pA.info := tA.info; ti := tA.next;

{построена копия для первого элемента списка} while ti <> nil do begin

new (q); {1}

qA.info := t1A.info; {2} p1A.next := q; {3} p1 := q; {4} t1:= t1A.next {5} end;

p1A.next := nil {конец списка}

end

Дмитриева M.B.

Рис. 4. Список и его копия после просмотра первых элементов

элементу списка копии. В {4} установили указатель р1 на последний элемент копии. И, наконец, в {5} осуществлен переход к обработке следующего элемента списка.

Рис. 4 соответствует ситуации, когда просмотрены первые элементы списка, для них построена копия, указатель р установлен на первый элемент, указатель р1 на последний элемент построенной копии, указатель Ы установлен на первый элемент «хвоста» списка, который еще предстоит обработать.

ВСТАВКА И УДАЛЕНИЕ ЭЛЕМЕНТОВ СПИСКА

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

ВСТАВКА ЭЛЕМЕНТА В УПОРЯДОЧЕННЫЙ СПИСОК. ВАРИАНТ 1

Пусть задан список, значения информационных полей которого упорядочены по возрастанию. Требуется описать процедуру,

Ло&ый ffykeefyefcc& ßcfcaßuffai

зммеН&ом списка.

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

Рассмотрим следующий алгоритм решения задачи. Пусть указатель cur «пробегает» по списку, когда указатель установлен на какой-либо элемент списка, анализируется информационное поле элемента, непосредственно следующего за элементом с указателем cur. Если окажется, что значение информационного поля анализируемого элемента больше образца, то просмотр списка следует прекратить.

Нашли элемент в линейном списке, перед которым следует вставить новый элемент, при этом упорядоченность списка не будет нарушена.

Отдельно рассматриваются случаи, когда список пуст, и случай, когда новый элемент требуется вставить перед первым элементом списка. Процедура вставки элемента в упорядоченный список, представлена в листинге 3.

На рис. 5 изображена ситуация, когда найден элемент, перед которым требуется

Рис. 5. Вставка элемента в упорядоченный список

Рис. 6. Список после вставки нового элемента

Листинг 3. Процедура вставки элемента в упорядоченный список. Вариант1

procedure add_sort (var t: list; r: elem_list); var p,cur: list;

begin new (p); pA.info := r; pA.next := nil; if t = nil then t := p else if r < tA.info

then begin pA.next := t; t := p end else

begin cur := t;

while curA.next <> nil do if curA.nextA.info > r then break

else cur := curA.next; pA.next := curA.next; {1} curA.next := p {2}

end

end

вставить новый элемент списка. В точке процедуры {1} установлена связь между новым элементом и тем, перед которым элемент вставляется.

Список на рис. 6 соответствует точке {2}, когда изменен указатель рассматриваемого элемента, он устанавливается на новый, только что созданный элемент, тем самым элемент включен в список.

ВСТАВКА ЭЛЕМЕНТА В УПОРЯДОЧЕННЫЙ СПИСОК. ВАРИАНТ 2

Рассмотри еще один вариант решения задачи о вставки элемента в упорядоченный список. В языке Turbo Pascal определена операция @, выдающая указатель на переменную, являющуюся операндом этой операции. В следующей процедуре перемен-

Р..

-Vs-.

ж

у

Рассмотрим jaf&vy ис&иагefttcfr uj списка

ная cur описана как указатель элемента типа list, который в свою очередь является указателем на элемент типа elem. Можно сказать, что переменная cur является указателем на указатель. В точке программы {1} ситуация такая, как на рис. 7.

Процедура вставки элемента в упорядоченный список приведена в листинге 4.

Для лучшего понимания работы процедуры следует рассмотреть случаи вставки элемента перед первым элементом списка, за последним элементом списка, вставки в середину списка. Для каждого из случаев построить конкретные списки и проследить, как изменяются связи между элементами в разных точках процедуры.

УДАЛЕНИЕ ИЗ СПИСКА ЭЛЕМЕНТОВ С ЗАДАННЫМ ИНФОРМАЦИОННЫМ ПОЛЕМ

Рассмотрим задачу исключения из списка элементов с заданным информационным полем. Опишем процедуру, которая удаля-

Рис. 7. Просмотр первого элемента списка

Дмитриева М.В.

Листинг 4. Вставка элемента в упорядоченный список. Вариант 2

procedure inord (var t: list; r: elem list);

var q: list;

cur: Alist;

begin new(q) ;

if q = nil then begin writeln ('нет памяти'); exit end

else

begin cur := @t; {1}

while curA <> nil do

if curAA.info >= r

then break

else cur := g(curAA.next);

qA.info := r;

qA.next := curA;

curA :=q

end

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

end

ет из списка все элементы, информационные поля которых совпадает с заданным значением.

Как и в предыдущей процедуре, используется операция получения адреса объекта. При просмотре элементов списка исполь-

Рис. 8. Состояние списка перед удалением элемента

зуется указатель, значение которого также является указателем. При исключении элемента из списка, память, занимаемая элементом, возвращается системе. Текст процедуры удаления из списка элементов с заданным информационным полем приведен в листинге 5.

На рис. 8 представлен список, когда элемент, который требуется удалить, уже найден, связь между предыдущим и следующим элементом измененного списка установлена.

Следующим шагом при работе алгоритма будет возвращение памяти, занимаемой элементом списка, системе. Как и в преды-

Листинг 5. Удаление из списка элементов с заданным информационным полем

procedure del_list (var t:list; r:elem_list); var d: list;

cur: Alist; begin cur := @t;

while curA <> nil do begin if curAA.info = r then {исключаем элемент} begin d := curA;

cur :=dA.next; dispose (d)

end else

cur :=@(curAA.next)

end

end

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

ЗАДАЧИ

1. Опишите процедуру, которая по исходному списку строит «перевернутый» список, оставляя исходный список без изменения.

2. Опишите процедуру, которая по двум упорядоченным спискам строит третий, который является результатом слияния первых двух. Исходные списки должны остаться без изменений.

3. Опишите функцию, которая проверяет, является ли список симметричным. В

симметричном списке информационное поле первого элемента совпадает с информационным полем последнего элемента, информационное поле второго элемента с информационным полем предпоследнего элемента и т. д.

4. Опишите процедуры, реализующие теоретико-множественные операции, если каждое из множеств является списком (операции объединения, пересечения, разности).

5. Два полинома степени п и т представляются в виде списка. Информационное поле элемента списка содержит коэффициент и степень. Напишите процедуры, которые строят полином и вычисляют сумму, разность, произведение заданных полиномов. Результирующий полином также представляется списком.

@ Наши авторы. 2007 Our authors. 2007

Дмитриева Марина Валерьевна, доцент кафедры1 информатики математико-механического факультета Санкт-Петербургского государственного университета.

i Надоели баннеры? Вы всегда можете отключить рекламу.