Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по информатике.doc
Скачиваний:
118
Добавлен:
02.05.2014
Размер:
1.53 Mб
Скачать

Операции над списками

Основными операциями над списками являются:

  • переход к очередному элементу списка;

  • добавление в список нового элемента;

  • поиск заданного элемента;

  • удаление элемента из списка.

Выполнение этих операций основывается на использовании и изменении указателей.

В отличие от очередей и стеков, элемент в список может быть до­бавлен в любое место.

Создание пустого списка

Определим значение указателей для пустого списка. Пусть пере­менная us будет задавать адрес первого элемента списка свобод­ных мест, а переменная UN — адрес первого элемента списка. Для пустого списка US=1, un=0. Приведем пример создания пустого списка при помощи функции New.

void New()

{for (i=l; i<maxlist-l; i++)

List[1][i]=i+1;

List[1][maxlist]=0;

US=1;

UN=0;

}

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

Вид пустого списка приведен в таблице.

Таблица 1. Вид пустого списка

Добавление в список нового элемента

Для добавления элемента х в список необходимо в переменную Pos запомнить адрес первого элемента списка свободных мест. Затем нужно поместить по этому адресу элемент х и в качестве указателя на следующий элемент списка записать номер первого элемента списка. Теперь указателем первого элемента списка бу­дет указатель us, т. к. по его адресу записан новый элемент. Он из разряда свободных элементов переходит в разряд занятых. Ука­зателем списка свободных мест будет Pos, т. е. элемент, который следует в списке свободных мест за только что исключенным из него элементом.

Приведем пример кода функции Insert (int, int, int), которая добавляет элемент х в список.

void Insert{int US, int UN, int X)

{

if (Sp= =O) exit{l); // Список не содержит элементов

Pos=List[1][US]; // Находит адрес первого элемента // списка свободных мест

List[0][US]=X; // Помещает по этому адресу значение X

List[1][US]=UN; // В качестве указателя

//на следующий элемент помещает

// номер первого элемента списка

UN=US;

US=POS;

}

Рассмотрим подробно операцию добавления элемента х в список. Сначала указатель списка свободных мест US=1, а первый элемент списка UN=0. Добавим в список элемент а, используя функцию Insert (int, int, int). Вид обновленного списка приведен в таблице. Зна­чит, US = 2, a UN=A.

Таблица 2. Добавление в список элемента А

Добавим в список элемент в, используя функцию Insert(int, int, int). US=3, UB=B (таблица).

Таблица 3. Добавление в список элемента В

Аналогичным образом добавим в таблицу элементы C и d US=5, a UN=D.

Таблица 4. Список после добавлениям в него элементов C и D

Теперь список свободных позиций содержит элементы с индек­сами 5, 6, 7, 8, 9, 10, а первым элементом списка является эле­мент d. Логическое расположение элементов в списке будет d, с, B, A. Этот порядок определяется указателями.

Поиск элемента в списке

Поиск элемента х в списке осуществляется следующим образом. Пе­ременной Lop присваиваем значение указателя первого элемента списка. Далее просматриваем список до тех пор, пока не найдем нужный элемент, либо не достигнем конца списка. Если по оконча­нию процедуры Lop=0, значит, в списке нет элемента со значением х.

Далее приведен пример функции Find (int, int, int), которая организовывает поиск в заданном списке элемента со значением х.

void Find(int X, int UN)

{

Lop=UN;

while (List[0][Lop]!=X && Lop!=0)

Lop=List[1][Lop]; // Присваивает переменной Lop ссылку

// на следующий элемент

}

Удаление элемента из списка

Чтобы удалить элемент х из списка, необходимо сначала найти его в списке, например, при помощи функции Find (int, int, int).

При удалении изменяется указатель записи элемента, идущего в списке перед элементом х таким образом, чтобы он указывал на элемент, идущий в списке после элемента х. Пусть Pos — индекс элемента массива, который необходимо уда­лить, а к — индекс элемента массива, который следует за элементом List[1] [POS].

Функция Delete (int, int, int) удаляет элемент х из списка. Далее приведен ее код.

void Delete (int K, int Pos, int US)

{

List[1][K]=List[1][Pos];

List[1][Pos]=US;

US=Pos;

}

Проследим удаление элемента х на примере списка из таблицы 4. Удалим элемент C из списка при помощи функции Delete (int, int, int).

Таблица 5. Удаление элемента из списка

После проделанных операций указатель списка свободных мест us=3, а первым элементом списка un=d.

Добавление элемента в список после заданного элемента

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

Эти операции реализует функция Insert_after(int, int, int). Далее приведен ее код.

void Insert_after (int Pos, int US, int E)

{

List[0][US]=E;

List[1][US]=List[1][Pos];

List[1][Pos]=US;

}

Здесь pos — это индекс элемента х.

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

Таблица 6. Добавление элемента D после элемента A

Сортировка списков

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

Если в задаче требуется отсортировать все элементы списка, то он сортируется как обычный массив, любым из ранее предло­женных методов (например, табл. 7, 8).

Таблица 7. Исходный список

Таблица 8. Отсортированный список

В некоторых задачах возникает необходимость сортировки спи­ска таким образом, чтобы по указателям можно было восстано­вить исходный список (например, табл. 9, 10).

Таблица 9. Исходный список

Таблица 10. Отсортированный список

В данном случае при сортировке необходимо менять местами не только элементы списка, но и их указатели. Обмен значениями можно организовать функцией swap(x,у), которая будет менять местами элементы и указатели списка в позициях х и у. Далее приведен код данной функции.

void Swap (int x, int y)

{

int Temp;

Temp=List[0][x];

List[0][y]=Temp;

Temp=List[1][x];

List[1][x]=List[1][y];

List[1][y]=Temp;

}

Данная сортировка списка необходима для того, чтобы на неко­тором i-ом шаге можно было вернуться на шаг под номером j и выполнить другие действия.

Слияние списков

Упорядоченные списки List_1 и List_2 длиной M и N сливаются в один упорядоченный список List_res длины M+N, если каж­дый элемент из List_1 и List_2 входит в List_res ровно один раз. В табл. 11—13 приведен пример слияния списков.

Таблица 11. Упорядоченный список List_1

Таблица 12. Упорядоченный список List_2

Таблица 13. Упорядоченный список List_res

Алгоритм слияния двух списков прост. Его основная идея выгля­дит следующим образом. Для слияния списков List_1 и List_2 список List_res сначала полагается пустым, а затем к нему по­следовательно приписывается первый узел из List_1 или List_2, оказавшийся меньшим и отсутствующий в List_res.