Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OTVET_OAIP.docx
Скачиваний:
22
Добавлен:
27.09.2019
Размер:
589.57 Кб
Скачать

15. Двухсвязный список. Удаление и вставка элемента в список.

Двусвязные списки дают возможность просмотра элементов в обоих направлениях и являются наиболее универсальными. Двусвязные списки используются для создания цепочек элементов, которые допускают частые операции включения, исключения, упорядочения, замены и пр. В односвязных и двусвязных списках последний элемент содержит указатель NULL для обозначения факта окончания последовательности. Аналогично первый элемент двусвязного списка содержит указатель NULL на предыдущий элемент. В этом случае работа с первым и последним элементом списка имеет свои особенности. В качестве альтернативы может быть предложен циклический список, у которого последний элемент ссылается на первый, а первый-на последний. Вставка. После ввода очередного числа с клавиатуры определяем его место в списке. Заметим, что при этом элемент может быть вставлен либо в начало списка, либо в конец его, либо в середину. Для того чтобы вставить в список элемент со значением 123 между двумя элементами, нужно найти эти элементы и запомнить их адреса (первый адрес – в переменной px, второй – в dх), после чего установить новые связи с элементом, в котором хранится значение 123.

Node *find(Node *const pbeg, int d){// Поиск элемента по ключу

Node *pv = pbeg ; while (pv){ if(pv->d == d)break; pv = pv->next;} return pv;}

Node *insert (Node *const pbeg, Node **pend, int key, int d)// Вставка элемента

{ if(Node *pkey = find(pbeg, key)) { Node *pv = new Node; pv->d = d;

pv->next = pkey->next;// установление связи нового узла с последующим

pv->prev = pkey;// установление связи нового узла с предыдущим

pkey->next = pv;// установление связи предыдущего узла с новым

if(pkey != *pend)(pv->next)->prev = pv;// установление связи последующего узла с новым

// Обновление указателя на конец списка; если узел вставляется в конец

else *pend = pv; return pv; } return 0; }

Удаление. В вашем списке должен быть как минимум указатель на начало списка. Если он есть, вы всегда сможете N раз перейти на следующий и таким образом добраться до элемента N. Затем переставить указатели (N-1) и (N+1) в обход N-го, а сам N-ый удалить (delete).

bool remove(Node **pbeg, Node **pend, int key)// Удаление элемента

{ if(Node *pkey = find(*pbeg, key)) { if (pkey == *pbeg)// проверяется,находится ли удаляемый элемент в начале списка { *pbeg = (*pbeg)->next;// если да,то надо скорректировать указатель pbeg на начало списка так, чтобы он указывал на следующий элемент в списке, адрес которого находится в поле next первого элемента (*pbeg)->prev =0;// обнуляется указатель на предыдущий элемент}

else if (pkey == *pend)// если удаляемый элемент находится в конце списка, требуется сместить указатель pend конца списка на предыдущий элемент, адрес которого можно получить из поля prev последнего элемента

{*pend = (*pend)->prev; (*pend)->next=0;// обнуляется указатель на следующий элемент } else // Если удаление происходит из середины списка, то нужно лишь обеспечить двустороннюю связь предыдущего и последующего элементов

{ (pkey->prev)->next = pkey->next; (pkey->next)->prev = pkey->prev; } delete pkey; return true; } return false; }

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]