Двунаправленные списки - EcsFlash/DataTypes GitHub Wiki

Исходный код - тут

Суть

Теперь у нас в узле появляется еще одна "стрелочка", которая позволяет нам бегать назад по списку.

Структура узла

struct Node {
	T data;
	Node* next;
	Node* prev;
	Node(T data) {
		this->data = data;
		next = nullptr;
		prev = nullptr;
	}
};

Инициализация списка (создание первого элемента списка).

DLList() {
	head = nullptr;
	tail = nullptr;
}

Проверка на пустоту.

bool isEmpty() {
	return head == nullptr;
}

Добавление элемента в список после заданного элемента (заданный элемент определяется указателем)

void addAfter(Node* whereTo, T element) {
	if (whereTo) {
		if (whereTo->next) {
			Node* newElement = new Node(element);
			newElement->next = whereTo->next;
			newElement->prev = whereTo;
			whereTo->next->prev = newElement;
			whereTo->next = newElement;
		}
		else {
			Node* newElement = new Node(element);
                        newElement->next = whereTo->next;
                        newElement->prev = whereTo;
                        whereTo->next = newElement;
                        tail = newElement;
		}
	}
}

Добавление элемента в список перед заданным элементом (заданный элемент определяется указателем)

void addBefore(Node* whereTo, T element) {
	if (whereTo) {
		if (whereTo->prev) {
			addAfter(whereTo->prev, element);
		}
		else {
			addToHead(element);
		}
	}
}

Удаление элемента(я художник я так вижу)

void deleteNode(Node* node) {
	if (node) {
		if (node->next && node->prev) {
			node->next->prev = node->prev;
			node->prev->next = node->next;
			delete node;
			node = nullptr;
		}
		else if (node->next && !node->prev) {
			node->next->prev = node->prev;
			head = node->next;
			delete node;
			node = nullptr;
		}
		else if (!node->next && node->prev) {
			node->prev->next = node->next;
			tail = node->prev;
			delete node;
			node = nullptr;
		}
		else if (!node->next && !node->prev) {
			head = tail = nullptr;
			delete node;
			node = nullptr;
		}
	}
}

Данную функцию мы будем использовать для операций, описанных далее

Удаление элемента из списка после заданного элемента (заданный элемент определяется указателем)

void deleteAfter(Node* whereTo) {
	deleteNode(whereTo->next);
}

Удаление элемента из списка перед заданным элементом (заданный элемент определяется указателем)

void deleteBefore(Node* whereTo) {
	deleteNode(whereTo->prev);
}

Создание списка в прямом/обратном порядке

DLList(T arr[], int size, bool reversed) {
	if (reversed) {
		for (int i = 0; i < size; i++) {
			addToHead(arr[i]);
		}
	}
	else {
		for (int i = size-1; i >= 0; i--) {
			addToHead(arr[i]);
		}
	}
}

Создание списка упорядоченно

DLList(T arr[], int size) {
	T temp;
	for (int i = 0; i < size; i++) {
		for (int j = 0; j < size - 1; j++) {
			if (arr[i] < arr[j]) {
				temp = arr[j];
				arr[j] = arr[i];
				arr[i] = temp;
			}
		}
	}
	for (int i = 0; i < size; i++) {
		addToHead(arr[i]);
	}
}

Печать в обычном/обратном направлении

void print(bool reversed = false) {
	if (!reversed) {
		Node* temp = head;
		while (temp != nullptr) {
			cout << temp->data << " ";
			temp = temp->next;
		}
	}
	else {
		Node* temp = tail;
		while (temp != nullptr) {
			cout << temp->data << " ";
			temp = temp->prev;
		}
	}
}

Уничтожение списка

~DLList() {
	clear();
}
void clear() {
	while (!isEmpty())
	{
		deleteNode(head);
	}
}
⚠️ **GitHub.com Fallback** ⚠️