Двусвязный список — это тип связанного списка, в котором каждый узел имеет ссылки как на следующий узел, так и на предыдущий узел. Это позволяет эффективно выполнять операции вставки и удаления, а также обход списка в обоих направлениях (т. е. вперед и назад).
В двусвязном списке каждый узел обычно имеет два поля: data
и next
, в которых хранится значение узла и ссылка на следующий узел в списке соответственно. В дополнение к этим двум полям каждый узел в двусвязном списке также имеет другое поле с именем prev
, в котором хранится ссылка на предыдущий узел в списке.
Вот пример узла двусвязного списка в C:
struct Node { int data; struct Node* next; struct Node* prev; };
Чтобы создать двусвязный список, нам сначала нужно создать структуру Node
и выделить для нее память с помощью функции malloc
. Затем мы можем присвоить значения полям data
, next
и prev
структуры Node
.
Вот пример создания двусвязного списка и вставки в него некоторых узлов:
struct Node* head = NULL; struct Node* second = NULL; struct Node* third = NULL; // allocate memory for the nodes head = (struct Node*)malloc(sizeof(struct Node)); second = (struct Node*)malloc(sizeof(struct Node)); third = (struct Node*)malloc(sizeof(struct Node)); // set the data for the nodes head->data = 1; second->data = 2; third->data = 3; // set the next and prev pointers for the nodes head->next = second; head->prev = NULL; second->next = third; second->prev = head; third->next = NULL; third->prev = second;
В приведенном выше примере мы создали три узла и присвоили значения их data
полям. Мы также устанавливаем указатели next
и prev
для каждого узла, связывая их вместе, чтобы сформировать двусвязный список. Узел head
указывает на второй узел, который, в свою очередь, указывает на третий узел, образуя цепочку узлов. Указатели prev
для каждого узла указывают на предыдущий узел в списке, что позволяет нам перемещаться по списку в обоих направлениях.
Чтобы пройти по двусвязному списку, мы можем начать с узла head
и следовать указателям next
, пока не достигнем конца списка. Мы также можем начать с последнего узла и следовать указателям prev
, чтобы пройти по списку в обратном направлении.
Вот пример обхода двусвязного списка в обоих направлениях:
// traversing the list forwards struct Node* current = head; while (current != NULL) { printf("%d ", current->data); current = current->next; } // traversing the list backwards current = third; while (current != NULL) { printf("%d ", current->data); current = current->prev; }
В приведенном выше примере мы начинаем с узла head
и перемещаемся по списку вперед, следуя указателям next
. По мере продвижения мы печатаем поле data
каждого узла. Затем мы начинаем с узла third
и перемещаемся по списку в обратном направлении, следуя указателям prev
.