Лекция
Привет, сегодня поговорим про двусвязные списки анимированые ы сравнение списков, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое двусвязные списки анимированые ы сравнение списков, массивов , настоятельно рекомендую прочитать все из категории Структуры данных.
. Об этом говорит сайт https://intellect.icuВ отличие от односвязных линейных списков, двусвязные, помимо полей data и next, имеют поле prev (указатель на предыдущий элемент списка):
type Node<T> = class data: T; prev, next: Node<T>; constructor (d: T; p, n: Node<T>); begin data := d; prev := p; next := n; end; end;
В случае двусвязного списка нам достаточно иметь ссылку на любой узел, тогда все остальные можно найти. Однако, для удобства, будем считать, что у нас есть две ссылки:
Удаление первого элемента списка +-------+ +-------+ +-------+ \/\/\->|данные | |данные | |данные | +---+---+ +---+---+ +---+---+ | 0 | |--->| | |--->| | 0 | +---+-A-+ +-|-+-A-+ +-|-+---+ |________| |________| превращается в +-------+ +-------+ +-------+ |удален | \/\/\->|данные | |данные | +---+---+ +---+---+ +---+---+ | 0 | 0 | | 0 | |--->| | 0 | +---+---+ +---+-A-+ +-|-+---+ |________| Удаление элемента из середины списка +-------+ +-------+ +-------+ \/\/\->|данные | |данные | |данные | +---+---+ +---+---+ +---+---+ | 0 | |--->| | |--->| | 0 | +---+-A-+ +-|-+-A-+ +-|-+---+ |________| |________| превращается в ___________________ | | +-------+ | +-------+ +---V---+ \/\/\->|данные | | |удален | |данные | +---+---+ | +---+---+ +---+---+ | 0 | |-' | 0 | 0 |--->| | 0 | +---+-A-+ +---+---+ +-|-+---+ |_____________________| Удаление первого элемента списка +-------+ +-------+ +-------+ \/\/\->|данные | |данные | |данные | +---+---+ +---+---+ +---+---+ | 0 | |--->| | |--->| | 0 | +---+-A-+ +-|-+-A-+ +-|-+---+ |________| |________| превращается в +-------+ +-------+ +-------+ \/\/\->|данные | |данные | |удален | +---+---+ +---+---+ +---+---+ | 0 | |--->| | 0 |--->| 0 | 0 | +---+-A-+ +-|-+---+ +---+---+ |________| |
Рис. 22.7. Удаление элемента двусвязного списка
Замечание. При выполнении любой операции нужно следить за возможными изменениями head и tail.
head := nil; tail := nil;
Примечание. Если изначально список был пуст, после добавления элемента надо не забыть сделать tail указывающим на него.
head := new Node<T>(0, nil, head); if head.next <> nil then head.next.prev := head else // если список был пуст tail := head;
tail := new Node<T>(2, tail, nil); if tail.prev <> nil then tail.prev.next := tail else // если список был пуст head := tail;
head := head.next; if head = nil then tail := nil else head.prev := nil;
tail := tail.prev; if tail = nil then head := nil else tail.next := nil;
if cur = head then // вставка в начало else begin cur.prev := new Node<T>(3, cur.prev, cur); cur.prev.prev.next := cur.prev; end;
if cur = tail then // вставка в конец else begin cur.next := new Node<T>(3, cur, cur.next); cur.next.next.prev := cur.next; end;
if cur = head then // удаление из начала else if cur = tail then // удаление из конца else begin cur.prev.next := cur.next; cur.next.prev := cur.prev; cur := cur.next; end;
Пример.
Дан двусвязный линейный список с целыми значениями.
Удалить все его отрицательные элементы.
var list: DoublyLinkedList<integer>; // создание списка var cur := list.head; while cur <> nil do if cur.data < 0 then cur := list.RemoveAt(cur) else cur := cur.next;
type Node<T> = class data: T; prev, next: Node<T>; constructor (d: T; p, n: Node<T>); begin data := d; prev := p; next := n; end; end; DoubleLinkedList<T> = class head, tail: Node<T>; constructor; begin head := nil; tail := nil; end; procedure AddFirst(d: T); begin head := new Node<T>(d, nil, head); if head.next <> nil then head.next.prev := head else // если список был пуст tail := head; end; procedure AddLast(d: T); begin tail := new Node<T>(d, tail, nil); if tail.prev <> nil then tail.prev.next := tail else // если список был пуст head := tail; end; procedure DeleteFirst; begin head := head.next; if head = nil then tail := nil else head.prev := nil; end; procedure DeleteLast; begin tail := tail.prev; if tail = nil then head := nil else tail.next := nil; end; procedure InsertBefore(cur: Node<T>; d: T); begin if cur = head then AddFirst(d) else begin cur.prev := new Node<T>(d, cur.prev, cur); cur.prev.prev.next := cur.prev; end; end; procedure InsertAfter(cur: Node<T>; d: T); begin if cur = tail then AddLast(d) else begin cur.next := new Node<T>(d, cur, cur.next); cur.next.next.prev := cur.next; end; end; function RemoveAt(cur: Node<T>): Node<T>; begin if cur = head then begin DeleteFirst; Result:=head; end else if cur = tail then begin DeleteLast; Result:=nil; end else if cur = tail then begin DeleteLast; result := nil; end else begin cur.prev.next := cur.next; cur.next.prev := cur.prev; result := cur.next; end; end; procedure Print; begin var cur := head; while cur <> nil do begin writeln(cur.data); cur := cur.next; end; end; procedure PrintReverse; begin var cur := tail; while cur <> nil do begin writeln(cur.data); cur := cur.prev; end; end; end;
по количеству операция (n - кол-во элементов)
Массив | Список | |
---|---|---|
Вставка в конец, удаление из конца | ||
Вставка в начало, удаление из начала | ||
Вставка в середину, удаление из середины | ||
Проход | ||
Доступ по индексу | ||
Поиск |
Надеюсь, эта статья про двусвязные списки анимированые ы сравнение списков, была вам полезна, счастья и удачи в ваших начинаниях! Надеюсь, что теперь ты понял что такое двусвязные списки анимированые ы сравнение списков, массивов и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Структуры данных
Из статьи мы узнали кратко, но содержательно про двусвязные списки анимированые ы сравнение списков
Комментарии
Оставить комментарий
Структуры данных
Термины: Структуры данных