Статические выпуклые оболочки: Джарвис, Грэхем, Эндрю, Чен, QuickHull — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Алгоритм Джарвиса)
(Алгоритм Джарвиса)
Строка 6: Строка 6:
 
== Описание Алгоритма ==
 
== Описание Алгоритма ==
  
1) Возьмем самую правую нижнюю точку <tex>p_0</tex> нашего множества. <tex>p_0</tex> лежит в выпуклой оболочке, поэтому добавляем ее в ответ.
+
[[File:Temp.gif|thumb|250px|Промежуточный шаг алгоритма]]
  
2) На каждом следующем шаге для последнего добавленного <tex>p_i</tex> ищем <tex>p_{i + 1}</tex> с максимальным полярным углом относительно <tex>p_i</tex> (Если углы равны, надо сравнивать по расстоянию). Добавляем <tex>p_{i + 1}</tex> в ответ. Если <tex>p_{i + 1} == p_0</tex> , заканчиваем алгоритм.
+
1) Возьмем самую правую нижнюю точку <tex>p_0</tex> нашего множества. Добавляем ее в ответ.
 +
 
 +
2) На каждом следующем шаге для последнего добавленного <tex>p_i</tex> ищем <tex>p_{i + 1}</tex> среди всех недобавленных точек и <tex>p_0</tex> с максимальным полярным углом относительно <tex>p_i</tex> (Если углы равны, надо сравнивать по расстоянию). Добавляем <tex>p_{i + 1}</tex> в ответ. Если <tex>p_{i + 1} == p_0</tex> , заканчиваем алгоритм.
 +
 
 +
== Корректность ==
 +
 
 +
Точка <tex>p_0</tex>, очевидно, принадлежит оболочке. На каждом шаге мы получаем прямую <tex>p_{i-1}p_i</tex>, по построениению которой все точки множества лежат слева от нее. Значит эти точки принадлежат выпуклой оболочке.
 +
 
 +
== Псевдокод ==
 +
 
 +
Подаем в функцию исходное множество S, возвращаем позицию <tex>k</tex> - в <tex>S[1..k - 1]</tex> будет хранится наша оболочка.
 +
<tex>turn(a, b, c)</tex> - модифицированная функция поворота, учитывающая случай, когда точки лежат на одной прямой.
 +
 
 +
  Jarvis(S)
 +
    for i = 1..n
 +
      if S[i] is right and higher than S[1]
 +
        swap(S[1], S[i])
 +
    k = 1
 +
    do
 +
      for i = 1 and k+1..n
 +
        if (turn(S[k+1], S[i], S[k]))
 +
          swap(S[k+1], S[k])
 +
      k++;
 +
    while S[k-1] != S[1]
 +
     
 +
 
 +
== Сложность ==
 +
 
 +
Добавление каждой точки в ответ занимает <tex>O(n)</tex> времени, всего точек будет <tex>k</tex>, поэтому итоговая сложность <tex>O(nk)</tex>.
  
 
= Алгоритм Грехэма =
 
= Алгоритм Грехэма =

Версия 09:36, 13 января 2014

Конспект не готов.

Алгоритм Джарвиса

По-другому "Заворачивание подарка"

Описание Алгоритма

Промежуточный шаг алгоритма

1) Возьмем самую правую нижнюю точку [math]p_0[/math] нашего множества. Добавляем ее в ответ.

2) На каждом следующем шаге для последнего добавленного [math]p_i[/math] ищем [math]p_{i + 1}[/math] среди всех недобавленных точек и [math]p_0[/math] с максимальным полярным углом относительно [math]p_i[/math] (Если углы равны, надо сравнивать по расстоянию). Добавляем [math]p_{i + 1}[/math] в ответ. Если [math]p_{i + 1} == p_0[/math] , заканчиваем алгоритм.

Корректность

Точка [math]p_0[/math], очевидно, принадлежит оболочке. На каждом шаге мы получаем прямую [math]p_{i-1}p_i[/math], по построениению которой все точки множества лежат слева от нее. Значит эти точки принадлежат выпуклой оболочке.

Псевдокод

Подаем в функцию исходное множество S, возвращаем позицию [math]k[/math] - в [math]S[1..k - 1][/math] будет хранится наша оболочка. [math]turn(a, b, c)[/math] - модифицированная функция поворота, учитывающая случай, когда точки лежат на одной прямой.

 Jarvis(S)
   for i = 1..n
     if S[i] is right and higher than S[1]
       swap(S[1], S[i])
   k = 1
   do 
     for i = 1 and k+1..n 
       if (turn(S[k+1], S[i], S[k]))
         swap(S[k+1], S[k])
     k++;
   while S[k-1] != S[1]
     

Сложность

Добавление каждой точки в ответ занимает [math]O(n)[/math] времени, всего точек будет [math]k[/math], поэтому итоговая сложность [math]O(nk)[/math].

Алгоритм Грехэма

Описание Алгоритма

Пример

Псевдокод

Сложность

Алгоритм Эндрю

Алгоритм Чена

Алгоритм QuickHull