Двунаправленный (или двусвязный) список – это список, который состоит из последовательности элементов, каждый из которых содержит информационную часть (данные) и два указателя на соседние элементы (на следующий и предыдущий элементы). В пространстве имен .NET C# System.Collections.Generic содержится класс LinkedList<T>, реализующий двунаправленный (двусвязный список).
В обычном универсальном списке List<T> каждый элемент — это объект типа T, в то время, как в LinkedList<T> каждый узел — это объект класса LinkedListNode<T>. Класс LinkedListNode<T> имеет следующие свойства:
Value— само значение узла, представленное типомTNext -ссылка на следующий элемент типаLinkedListNode<T>в списке. Если следующий элемент отсутствует, то имеет значениеnullPrevious: ссылка на предыдущий элемент типаLinkedListNode<T>в списке. Если предыдущий элемент отсутствует, то имеет значениеnull
Для работы со списком элементов у LinkedList<T> используются следующие методы:
AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)— вставляет узелnewNodeв список после узлаnode.AddAfter(LinkedListNode<T> node, T value)— вставляет в список новый узел со значениемvalueпосле узлаnode.AddBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)— вставляет в список узелnewNodeперед узломnode.AddBefore(LinkedListNode<T> node, T value)— вставляет в список новый узел со значениемvalueперед узломnode.AddFirst(LinkedListNode<T> node)— вставляет новый узел в начало спискаAddFirst(T value)— вставляет новый узел со значениемvalueв начало спискаAddLast(LinkedListNode<T> node)— вставляет новый узел в конец спискаAddLast(T value)— вставляет новый узел со значениемvalueв конец спискаRemoveFirst()— удаляет первый узел из списка. После удаления новым первым узлом становится узел, следующий за удаленнымRemoveLast()— удаляет последний узел из списка
Двусвязные списки нашли широкое применения при решении каких-либо геометрических задач. Например, двусвязным списком удобно представлять множество вершин многоугольника — каждый узел списка будет описывать очередную вершину многоугольника и, соответственно, можно достаточно легко определить какая вершина является предыдущей, а какая следующий.
Рассмотрим работу с двусвязным списком LinkedList<T> на примере решения задачи о нахождении площади многоугольника.
Практический пример использования двусвязного списка LinkedList<T> в C#
Итак, решам следующую практическую задачу: найдем площадь многоугольника, заданного списком координат (X, Y).
Задачу будем решать при условии, что многоугольник будет без самопересечений. Для решения этой задачи нам потребуется класс, хранящий данные о координатах вершины. Для этого можно воспользоваться уже имеющемся классом PointF из пространства имен System.или же написать свой собственный класс, например, такой:
public class Vertex
{
public double X { get; set; }
public double Y { get; set; }
public Vertex(double x, double y)
{
X = x;
Y = y;
}
}
Площадь многоугольника можно рассчитать с использованием следующей формулы:
где X0,Y0 = Xn+1,Yn+1 (координаты последней точки совпадают с первой). Таким образом, алгоритм расчёта площади многоугольника может быть следующим:
- Вершины
N+1вершин многоугольника — последняя вершина совпадает с первой. То есть, например, для четырехугольника мы зададим пять вершин. - В цикле от
0доNпроходим по вершинам многоугольника и считаем сумму по формуле выше - Полученную сумму делим на
2— это и будет площадь многоугольника.
Реализация представленного алгоритма на примере прямоугольника может выглядеть так:
class Program
{
static void Main(string[] args)
{
LinkedList<Vertex> vertices = new LinkedList<Vertex>();
vertices.AddLast(new Vertex(0.0, 0.0));
vertices.AddLast(new Vertex(0.0, 2.0));
vertices.AddLast(new Vertex(2.0, 2.0));
vertices.AddLast(new Vertex(2.0, 0.0));
vertices.AddLast(new Vertex(0.0, 0.0));
double sum = 0;
LinkedListNode<Vertex> vertex = vertices.First;
for (int i = 0; i < vertices.Count-1; i++)
{
sum += Abs(vertex.Value.X + vertex.Next.Value.X) * (vertex.Value.Y - vertex.Next.Value.Y);
vertex = vertex.Next;
}
double square = 0.5*sum;
Console.WriteLine($"Площадь многоугольника {square}");
}
}
Здесь задан четырехугольник (квадрат) со сторонами равными 2. Нетрудно посчитать, что площадь такого многоугольника будет равна четырем. Вывод консоли представленой выше программы будет следующим:
Это всего лишь один из примеров, когда нам может потребоваться двусвязный список LinkedList<T> в C#.
Итого
Сегодня мы на «живом» примере разобрались с тем, что из себя представляет двусвязный список LinkedList<T> в C# и рассчитали с его помощью площадь многоугольника. Двусвязный список отличается от обычного списка List<T> тем, что каждый его элемент — это объект, который помимо полезной информации (данных объекта) содержит также две ссылки — на предыдущий и следующий элементы списка.