Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

3.3. Вдвойне связанные списки 123

3.3 Вдвойне связанные списки

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

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

Заголовок и стражи трейлера

Чтобы упростить программирование, удобно добавить специальные узлы в обоих концах

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

Рисунок 3.12: вдвойне связанный список со стражами, заголовком и трейлером, отмечая концы списка. У пустого списка были бы эти стражи, указывающие друг на друга. Мы не показываем пустому указателю предыдущий указатель для заголовка, и при этом мы не показываем пустому указателю следующий указатель для трейлера.

3.3.1 Вставка во вдвойне связанный список

Из-за его двойной структуры связи возможно вставить узел в любом положении

в рамках вдвойне связанного списка. Учитывая узел v вдвойне связанного списка (который мог возможно быть заголовком, но не трейлером), позвольте z быть новым узлом, который мы хотим вставить

124 Глава 3. Множества, связанные списки и рекурсия

немедленно после v. Позвольте w быть узлом после v, то есть, w - узел, на который указывает следующая связь v. (Этот узел существует, так как у нас есть стражи.) Чтобы вставить z после v, мы связываем его в текущий список, выполняя следующие операции:

Выскажите предыдущее мнение связи z к v

Выскажите следующее мнение связи z к w выскажите предыдущее мнение связи w к z выскажите следующее мнение связи v к z

Этот процесс иллюстрирован в рисунке 3.13, где v указывает на узел, JFK, w указывает на PVD, и z указывает на новый узел BWI. Заметьте, что этот процесс работает, если v - какой-либо узел в пределах от заголовка к узлу только до трейлера.

(a)

(b)

Рисунок 3.13: Добавление нового узла после узла, хранящего JFK: (a) создание нового узла с элементом BWI и соединение его в; (b) после вставки.

3.3.2 Удаление из вдвойне связанного списка

Аналогично, легко удалить узел v из вдвойне связанного списка. Позвольте u быть узлом

только до v и w быть узлом только после v. (Эти узлы существуют, так как у нас есть стражи.), Чтобы удалить узел v, у нас просто есть u, и w указывают друг другу вместо к v. Мы именуем эту операцию как соединение из v. Мы выполняем следующие операции.

• Выскажите предыдущее мнение связи w к u

• Выскажите следующее мнение связи u к w • Удалите узел v

Этот процесс иллюстрирован в рисунке 3.14, где v - узел, PVD, u является узлом JFK, и w - узел SFO. Заметьте, что этот процесс работает, если v - какой-либо узел от заголовка до узла хвоста (узел только до трейлера).