Рубрики
Без рубрики

Список вдвойне связан в Python – сделал легко

Вдвойне связанный список – это структура данных, которая используется для хранения списков. Это очень похоже на связанные списки, но с несколькими дополнительными функциями. В этом руководстве мы

Автор оригинала: Pankaj Kumar.

Список вдвойне связан в Python – сделал легко

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

Предварительный реквизит: связанный список

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

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

Наиболее распространенным связным списком является «односторонний список» или просто «связанный список», в этом каждый элемент ссылается на следующий элемент в списке. Итак, чтобы получить доступ к 10-м пункту, нам нужно сначала получить доступ к 9-м пункту, потому что он ссылается на 10-й элемент. И как только мы получим доступ к 10-м пункту, он позволит нам получить доступ к 11-м пункту через ссылку, который имеет 10-й элемент.

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

Теперь давайте посмотрим на вдвойне связанные списки.

Что такое вдвойне связанный список?

Вдвойне связанный список также является списком, в котором узлы подключены через ссылки, но в этом случае каждый узел ссылается на следующий элемент, а также предыдущий элемент. Итак, как только мы получим доступ к 10-м узлу, мы можем получить доступ к 9-м узлу и 11-м узлу и получить доступ к конкретному узлу, нам нужно будет получить доступ к узлу перед ним или узлом после него.

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

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

Чтобы визуализировать, вдвойне связанный список выглядит что-то подобное:

Список вдвойне связан в списке ROP 2

В приведенном выше примере вы можете видеть, что в связанном списке есть четыре элемента/узла. Каждый узел имеет некоторые данные или контент, и каждый узел/ссылки на следующий и предыдущий узел списка. Предыдущая ссылка первого узла и следующая ссылка последнего узла не указывает на что-то, поэтому они хранят Нет (в случае питона).

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

Реализация вдвойне связанного списка в Python

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

1. Класс: узел

Для класса узла у нас есть только три члена в классе. Один для хранения данных, один для хранения следующего узла и один для предыдущего узла.

Определение класса будет выглядеть что-то подобное:

class Node:
    def __init__(self, data = None):
        self.data = data
        self.next = None
        self.previous = None

Здесь, изначально узлы не указывают на любой другой узел, и он может или не может иметь данные в зависимости от того, как он был создан.

2. Класс: вдвойне связанный список

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

Класс будет выглядеть что-то подобное:

class DLL:
    def __init__(self):
        self.head = None
        self.tail = None
        self.count = 0
        
    def __repr__(self):
        string = ""
        
        if(self.head == None):
            string += "Doubly Linked List Empty"
            return string
        
        string += f"Doubly Linked List:\n{self.head.data}"        
        start = self.head.next
        while(start != None):
            string += f" -> {start.data}"
            start = start.next
        return string
        
    def append(self, data):
        if self.head == None:
            self.head = Node(data)
            self.tail = self.head
            self.count += 1
            return
        
        self.tail.next = Node(data)
        self.tail.next.previous = self.tail
        self.tail = self.tail.next
        self.count += 1
        
    def insert(self, data, index):
        if (index > self.count) | (index < 0):
            raise ValueError(f"Index out of range: {index}, size: {self.count}")
            
        if(index == self.count):
            self.append(data)
            return
            
        if(index == 0):
            self.head.previous = Node(data)
            self.head.previous.next = self.head
            self.head = self.head.previous
            self.count += 1
            return
        
        start = self.head
        for _ in range(index):
            start = start.next
        start.previous.next = Node(data)
        start.previous.next.previous = start.previous
        start.previous.next.next = start
        start.previous = start.previous.next
        self.count += 1
        return
    
    def remove(self, index):
        if (index >= self.count) | (index < 0):
            raise ValueError(f"Index out of range: {index}, size: {self.count}")
        
        if index == 0:
            self.head = self.head.next
            self.head.previous = None
            self.count -= 1
            return
            
        if index == (self.count - 1):
            self.tail = self.tail.previous
            self.tail.next = None
            self.count -= 1
            return
        
        start = self.head
        for i in range(index):
            start = start.next
        start.previous.next, start.next.previous = start.next, start.previous
        self.count -= 1
        return
    
    def index(self, data):
        start = self.head
        for i in range(self.count):
            if(start.data == data):
                return i
            start = start.next
        return None
    
    def size(self):
        return self.count
    
    def display(self):
        print(self)

Вышеуказанный класс имеет много членов, давайте обсудим их один за другим.

3. Метод __init__

В конструкторе мы объявляем три переменных. голова и хвост инициализируются с Нет , что означает, что в списке нет переменных в списке, и поэтому Считать также инициализируется с 0 Отказ

4. Метод __repr__

Метод __REPR__ вернет строку, которая распечатает связанный список. Таким образом, либо список пуста, в этом случае мы распечатаем это, либо список не пусто, поэтому мы распечатаем данные в каждом узле один за другим.

5. Способ добавления и вставки

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

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

Если указанная позиция находится в середине, то мы сначала доберемся до этой позиции, сделайте Следующий из узла до этой позиции указывают на новый узел, затем сделайте новый узел предыдущий Укажите на узел перед этой позицией, затем сделайте новый узел Следующий Укажите на узел в этой позиции и, наконец, мы делаем предыдущий узла в этом положении указывают на новый узел.

Мы также проверяем, если данный индекс действителен или нет, а если нет, мы можем поднять ValueError Отказ Кроме того, мы увеличиваем Считать После каждой успешной вставки операции.

6. Способ удаления

Чтобы удалить элемент, который мы должны указывать, где элемент должен быть удален. Если указанный индекс вне диапазона, мы поднимаем ValueError Отказ Если индекс 0, мы снимаем первый элемент, чтобы сделать это, мы делаем голова указать на второй узел. Если голова Это ноль, это означает, что список сейчас пусто, если нет, то мы должны сделать новый голова ‘s предыдущий магазин Нет Отказ

Точно так же, если индекс один меньше, чем размер списка, это означает, что мы должны удалить последний элемент, поэтому мы делаем хвост Укажите на второй последний узел, а затем сделайте новый хвост ‘s Следующий магазин Нет Отказ

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

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

7. Метод индекса, размера и отображения.

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

Размер Метод возвращает значение Считать Член класса, который хранит количество элементов в списке.

И Дисплей Метод печатает объект, который вызывает __repr__ Метод и возвращенная строка напечатаны на экран.

Выход

После выполнения нескольких утверждений в классе здесь вывод:

DLL init Добавить и вставить пример
DLL Удалить размер индекса и пример отображения

Заключение

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

Я надеюсь, что у вас было отличное время обучения, и увидимся в следующем руководстве.