Есть построенный граф, в котором все вершины заданы экземплярами класса Vertex, а грани - Edge. Vertex имеют координаты float x и float y, а Edge точки Vertex a и Vertex b, длину double length. Попытка написать алгоритм построения минимального остовного дерева из графа Делоне по алгоритму Прима не увенчалась успехом. Получалось подобное:
Где белые ребра - ребра моего "древа", а серые в совокупности с белыми - исходный граф. Вот код моего алгоритма:
List
В чем может быть ошибка?
Ответ
Мой алгоритм так и не заработал (возможно из-за того что я его не правильно понял). Вчера нашел другую формулировку этого алгоритма:
Инициализируются списки с данными: ребра, не включенные в дерево, вершины, включенные в дерево, и вершины, не включенные в дерево.
выбирается случайная начальная вершина, с которой начнется построение минимального остовного дерева.
Цикл while будет продолжаться до тех пор, пока все вершины графа не будут включены в дерево
А в цикле уже:
Производится поиск ребра с наименьшим весом, один конец которого – это вершина, входящая в дерево, а другой – нет/
Вершина, инцидентная найденному ребру, заносится в список использованных и удаляется из списка неиспользованных.
Найденное ребро заносится в список ребер, составляющих дерево, и удаляется из списка неиспользованных ребер.
Переписал код под свои цели:
List notUsedE = new List(DelaunayTree); //неиспользованные ребра есть копия ребер исходного графа
List notUsedV = new List(points); //неиспользованные вершины есть копия вершин исходного графа
List usedV = new List(); //список вершин по которым "проехался" алгоритм
notUsedV[0].inUsedSide = true; //отмечаем что вершина используется
usedV.Add(notUsedV[0]); //заносим её в список использованных
notUsedV.Remove(usedV[0]); //удаляем из списка неспользованных
while (notUsedV.Count>0) //пока есть вершины над которыми можно работать
{
List doubleSideE = new List(); //создание списка ребер у которых одна вершина используется, а другая нет
foreach(Edge e in notUsedE) //для каждого неиспользованного ребра
{
if ((e.a.inUsedSide && !e.b.inUsedSide) || (e.b.inUsedSide && !e.a.inUsedSide)) doubleSideE.Add(e); //если у него одна вершина исп., а другая нет, то добавляем в список "двуликих"
}
Edge minE = doubleSideE[0]; //инициализация переменной для ребра, у которого минимальный вес
foreach(Edge e in doubleSideE) //для каждого "двуликого" ребра
{
if (e.weight < minE.weight) minE = e; //если его вес меньше веса минимального, то делаем его минимальным
}
if (!minE.a.inUsedSide) //если вершина a ребра minE не используется
{
notUsedV.Remove(minE.a); //то удаляем вершину a из использованных
minE.a.inUsedSide = true; //и делам её используемой
usedV.Add(minE.a);
} else { //а если b не используется
notUsedV.Remove(minE.b);
minE.b.inUsedSide = true; //то делаем её используемой
usedV.Add(minE.b);
}
minimalTree.Add(minE); //добавляем минимальное ребро в конечный граф
notUsedE.Remove(minE); //и удаляем его из неиспользованных, чтобы алгоритм не прошелся по нему еще раз
}
Комментариев нет:
Отправить комментарий