<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=41761&amp;view=findpost&amp;p=272156</guid>
        <pubDate>Sun, 28 Dec 2003 19:58:12 +0000</pubDate>
        <title>Очередь - углублённый курс</title>
        <link>https://forum.sources.ru/index.php?showtopic=41761&amp;view=findpost&amp;p=272156</link>
        <description><![CDATA[Krishkinn: <span class='tag-size' data-value='12' style='font-size:12pt;'><span class="tag-color tag-color-named" data-value="blue" style="color: blue"><strong class='tag-b'>Очереди</strong></span></span><br>
<br>
Значениями типа &quot;очередь элементов типа T&quot;, как и для стеков, являются последовательности значений типа T. Разница состоит в том, что берутся элементы не с конца, а с начала (а добавляются по-прежнему в конец).<br>
<br>
<span class='tag-u'>Операции с очередями:</span><ul class="tag-list"><li>Сделать_пустой (var x: очередь элементов типа T);</li><li>Добавить (t: T, var x: очередь элементов типа T);</li><li>Взять (var t: T, var x: очередь элементов типа T);</li><li>Пуста (x: очередь элементов типа T): boolean;</li><li>Очередной (x: очередь элементов типа T): T.</li></ul><br>
При выполнении команды &quot;Добавить&quot; указанный элемент добавляется в конец очереди. Команда &quot;Взять&quot; выполнима, лишь если<br>
очередь не является пустой, и забирает из нее первый (положенный туда раньше всех) элемент, помещая его в t. Значением функции &quot;Очередной&quot; (определенной для непустой очереди) является первый элемент очереди.<br>
<br>
Английские названия стеков - Last In First Out  (последним вошел - первым вышел, <strong class='tag-b'>LIFO</strong>), а очередей - First In First Out (первым вошел - первым вышел, <strong class='tag-b'>FIFO</strong>).<br>
<br>
<span class="tag-color tag-color-named" data-value="blue" style="color: blue"><strong class='tag-b'>Реализация очередей в массиве.</strong></span><br>
<br>
2.1. Реализовать операции с очередью ограниченной длины так, чтобы количество действий для каждой операции было ограничено константой, не зависящей от длины очереди.<br>
<br>
<span class='tag-u'>Решение</span><br>
Будем хранить элементы очереди в соседних элементах массива. Тогда очередь будет прирастать справа и убывать слева. Поскольку при этом она может дойти до края, свернем массив в окружность.<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;Введем массив Содержание: array [0..n-1] of T и переменные</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Первый: 0..n-1,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Длина : 0..n.</div><div class="code_line">При этом элементами очереди будут</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Содержание [Первый], Содержание [Первый + 1],...,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Содержание [Первый + Длина - 1], где сложение выполняется &nbsp;по &nbsp;модулю n.</div><div class="code_line">&nbsp;</div><div class="code_line"><span style='color:red'>Предупреждение: </span></div><div class="code_line">Если вместо этого ввести переменные Первый и Последний, принимающие значения в вычетах</div><div class="code_line">по модулю n, то пустая очередь может быть спутана с очередью из n элементов.</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
Операции выполняются так:<ul class="tag-list"><li>Сделать пустой:<br>
        Длина := 0;<br>
        Первый := 0;</li><li>Добавить элемент:<br>
        {Длина &lt; n}<br>
        Содержание [(Первый + Длина) mod n] := элемент;<br>
        Длина := Длина + 1;</li><li>Взять элемент;<br>
        {Длина &gt; 0}<br>
        элемент := Содержание [Первый];<br>
        Первый := (Первый + 1) mod n;<br>
        Длина := Длина - 1;</li><li>Пуста = (Длина = 0);</li><li>Очередной = Содержание [Первый];</li></ul><br>
<strong class='tag-b'>2.2.</strong>  (Сообщил А.Г.Кушниренко) Придумать способ моделирования очереди с помощью двух стеков (и фиксированного числа переменных типа T). При этом отработка n операций с очередью (начатых, когда очередь была пуста) должна требовать  порядка <em class='tag-i'>n</em> действий.<br>
<br>
<span class='tag-u'>Решение</span><br>
Инвариант: стеки, составленные концами, образуют очередь. Перечисляя элементы одного стека вглубь и затем элементы второго наружу, мы перечисляем все элементы очереди от первого до последнего.<br>
<br>
Ясно, что добавление сводится к добавлению к одному из стеков, а проверка пустоты - к проверке пустоты обоих стеков.<br>
Если мы хотим взять элемент, есть два случая.<br>
<ol class="tag-list" type="1"><li>Если стек, где находится начало очереди, не пуст, то берем из него элемент.</li><li>Если он пуст, то предварительно переписываем в него все элементы второго стека, меняя порядок (это происходит само собой<br>
при перекладывании из стека в стек) и сводим дело к первому случаю. Хотя число действий на этом шаге и не ограничено константой, но требование задачи выполнено, так как каждый элемент очереди может участвовать в этом процессе не более одного раза.</li></ol><br>
<strong class='tag-b'>2.3.</strong> <span class="tag-color tag-color-named" data-value="orange" style="color: orange">Деком</span> называют структуру, сочетающую очередь и стек:<br>
класть и забирать элементы можно с обоих концов. Как реализовать дек ограниченного размера на базе массива так, чтобы каждая операция требовала ограниченного числа действий?<br>
<br>
<strong class='tag-b'>2.4.</strong> (Сообщил А.Г.Кушниренко.) Имеется дек элементов типа T и конечное число переменных типа T и целого типа. В начальном состоянии в деке некоторое число элементов. Составить программу, после исполнения которой в деке остались бы те же самые элементы, а их число было бы в одной из целых переменных.<br>
<br>
<span class='tag-u'>Указание</span><ul class="tag-list"><li>Элементы дека можно циклически переставлять, забирая с одного конца и помещая в другой. После этого, сделав столько же шагов в обратном направлении, можно вернуть все на место.</li><li>Как понять, прошли мы полный круг или не прошли?<br>
Если бы какой-то элемент заведомо отсутствовал в деке, то можно было бы его подсунуть и ждать вторичного появления. Но таких элементов нет. Вместо этого можно для данного n выполнить циклический сдвиг на n дважды, подсунув разные элементы, и посмотреть, появятся ли разные элементы через n шагов.</li></ul><br>
<strong class='tag-b'>Применение очередей.</strong><br>
<strong class='tag-b'>2.5.</strong> Напечатать в  порядке возрастания первые n натуральных чисел, в разложение которых на простые множители входят только числа 2, 3, 5.<br>
<br>
<span class='tag-u'>Решение</span><br>
Введем три очереди x2, x3, x5, в которых будем хранить элементы, которые в 2 (3, 5) раз больше напечатанных, но еще не напечатаны. Определим процедуру<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;procedure напечатать_и_добавить (t: integer);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;| writeln (t);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;| добавить (2*t, x2);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;| добавить (3*t, x3);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;| добавить (5*t, x5);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;end;</div></ol></div></div></div></div><br>
<br>
Вот схема программы:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp;...сделать x2, x3, x5 пустыми</div><div class="code_line">&nbsp;&nbsp;напечатать_и_добавить (1);</div><div class="code_line">&nbsp;&nbsp;k := 1; { k - число напечатанных }</div><div class="code_line">&nbsp;&nbsp;{инвариант: &nbsp;напечатано &nbsp;в &nbsp;порядке &nbsp;возрастания k минимальных</div><div class="code_line">&nbsp;&nbsp;членов нужного множества; в очередях элементы, вдвое, втрое &nbsp;и</div><div class="code_line">&nbsp;&nbsp;впятеро &nbsp;большие напечатанных, но не напечатанные, расположен-</div><div class="code_line">&nbsp;&nbsp;ные в возрастающем порядке}</div><div class="code_line">&nbsp;&nbsp;while k &#60;&#62; n do begin</div><div class="code_line">&nbsp;&nbsp;| x := min (очередной (x2), очередной (x3), очередной (x5));</div><div class="code_line">&nbsp;&nbsp;| напечатать_и_добавить (x);</div><div class="code_line">&nbsp;&nbsp;| k := k+1;</div><div class="code_line">&nbsp;&nbsp;| ...взять x из тех очередей, где он был очередным;</div><div class="code_line">&nbsp;&nbsp;end;</div></ol></div></div></div></div><br>
<br>
<span class="tag-color tag-color-named" data-value="gray" style="color: gray">Пусть инвариант выполняется. Рассмотрим наименьший из ненапечатанных элементов множества; пусть это x. Тогда он делится нацело на одно из чисел 2, 3, 5, и частное также принадлежит множеству.<br>
<br>
Значит, оно напечатано. Значит, x находится в одной из очередей, и, следовательно, является в ней первым (меньшие напечатаны, а элементы очередей не напечатаны). Напечатав x, мы должны его изъять и добавить его кратные.<br>
<br>
Длины очередей не превосходят числа напечатанных элементов.<br>
</span><br>
<br>
<span class="tag-color tag-color-named" data-value="blue" style="color: blue"><strong class='tag-b'>Следующая задача</strong></span> связана с графами (к которым мы вернёмся в главе 9).<br>
<br>
Пусть задано конечное множество, элементы которого называют вершинами, а также некоторое множество упорядоченных пар вершин, называемых ребрами. В этом случае говорят, что задан <span class="tag-color tag-color-named" data-value="orange" style="color: orange">ориентированный граф</span>. Пару &lt;p, q&gt; называют <span class="tag-color tag-color-named" data-value="orange" style="color: orange">ребром</span> с началом p и концом q; говорят также, что оно выходит из вершины p и входит в вершину q. Обычно вершины графа изображают точками, а ребра - стрелками, ведущими из начала в конец. (В соответствии с определением из данной вершины в данную ведет не более одного ребра; возможны ребра, у которых начало совпадает с концом.)<br>
<br>
<strong class='tag-b'>2.6.</strong> Известно, что ориентированный граф связан, т. е. из любой вершины можно пройти в любую по ребрам. Кроме того, из каждой вершины выходит столько же ребер, сколько входит. Доказать, что существует замкнутый цикл, проходящий по каждому ребру ровно один раз. Составить алгоритм отыскания такого цикла.<br>
<br>
<span class='tag-u'>Решение</span><br>
<span class="tag-color tag-color-named" data-value="orange" style="color: orange">Змеей</span> будем называть непустую очередь из вершин, в которой любые две вершины соединены ребром графа (началом является та вершина, которая ближе к началу очереди). Стоящая в начале очереди вершина будет хвостом змеи, последняя - головой. На рисунке змея изобразится в виде цепи ребер графа, стрелки ведут от хвоста к голове. Добавление вершины в очередь соответствует росту змеи с головы, взятие вершины - отрезанию кончика хвоста.<br>
<br>
Вначале змея состоит из единственной вершины. Далее мы следуем такому правилу:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">while змея включает не все ребра do begin</div><div class="code_line">| if из головы выходит неиспользованное в змее ребро then begin</div><div class="code_line">| | удлинить змею этим ребром</div><div class="code_line">| end else begin</div><div class="code_line">| | {голова змеи в той же вершине, что и хвост}</div><div class="code_line">| | отрезать конец хвоста и добавить его к голове</div><div class="code_line">| | {&quot;змея откусывает конец хвоста&quot;}</div><div class="code_line">| end;</div><div class="code_line">end;</div></ol></div></div></div></div><br>
Докажем, что мы достигнем цели.<ol class="tag-list" type="1"><li>Идя по змее от хвоста к голове, мы входим в каждую вершину столько же раз, сколько выходим. Так как в любую вершину входит столько же ребер, сколько выходит, то невозможность выйти означает, что голова змеи в той же точке, что и хвост.</li><li>Змея не укорачивается, поэтому либо она охватит все рёбра, либо, начиная с некоторого момента, будет иметь постоянную длину. Во втором случае змея будет бесконечно &quot;скользить по себе&quot;. Это возможно, только если из всех вершин змеи не выходит неиспользованных ребер. В этом случае из связности следует, что змея проходит по всем рёбрам.</li></ol><br>
<span class='tag-u'>Замечание по реализации на Паскале</span><br>
Вершинами графа будем считать числа 1..n. Для каждой вершины i будем хранить число Out[ i ] выходящих из нее ребер, а также номера Num[ i ][1],...,Num[ i ][Out[ i ]] тех вершин, куда эти ребра ведут. В процессе построения змеи будем выбирать первое свободное  ребро. Тогда достаточно хранить для каждой вершины число выходящих из нее использованных ребер - это будут ребра, идущие в начале списка.<br>
<br>
<strong class='tag-b'>2.7.</strong> Доказать, что для всякого n существует последовательность нулей и единиц длины (2<sup class='tag-sup'>n</sup>) со следующим<br>
свойством: если &quot;свернуть ее в кольцо&quot; и рассмотреть все фрагменты длины n (их число равно (2<sup class='tag-sup'>n</sup>)), то мы получим все возможные последовательности нулей и единиц длины n. Построить алгоритм отыскания такой последовательности, требующий не более (C<sup class='tag-sup'>n</sup>) действий для некоторой константы C.<br>
<br>
<span class='tag-u'>Указание</span><br>
Рассмотрим граф, вершинами которого являются последовательности нулей и единиц длины (n-1). Будем считать, что из вершины x ведет ребро в вершину y, если x может быть началом, а y - концом некоторой последовательности длины n. Тогда из каждой вершины входит и выходит два ребра. Цикл, проходящий по всем ребрам, и даст требуемую последовательность.<br>
<br>
<strong class='tag-b'>2.8.</strong> Реализовать k очередей с ограниченной суммарной длиной n, используя память порядка n+k, причем каждая операция (кроме начальной, делающей все очереди пустыми) должна требовать ограниченного константой числа действий.<br>
<br>
<span class='tag-u'>Решение.</span><br>
Действуем аналогично ссылочной реализации стеков: мы помним (для каждой очереди) первого, каждый участник очереди помнит следующего за ним (для последнего считается, что за ним стоит фиктивный элемент с номером 0). Кроме того, мы должны для каждой очереди знать последнего (если он есть) - иначе не удастся добавлять. Как и для стеков, отдельно есть цепь свободных ячеек. Заметим, что для пустой очереди информация о последнем элементе теряет смысл - но она и не используется при добавлении.<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Содержание: array [1..n] of T;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Следующий: array [1..n] of 0..n;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Первый: array [1..k] of 0..n;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Последний: array [1..k] of 0..n;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Свободная : 0..n;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;procedure Сделать_пустым;</div><div class="code_line">&nbsp;&nbsp;| var i: integer;</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp;| for i := 1 to n-1 do begin</div><div class="code_line">&nbsp;&nbsp;| | Следующий [i] := i + 1;</div><div class="code_line">&nbsp;&nbsp;| end;</div><div class="code_line">&nbsp;&nbsp;| Следующий [n] := 0;</div><div class="code_line">&nbsp;&nbsp;| Свободная := 1;</div><div class="code_line">&nbsp;&nbsp;| for i := 1 to k do begin</div><div class="code_line">&nbsp;&nbsp;| | Первый [i]:=0;</div><div class="code_line">&nbsp;&nbsp;| end;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;function Есть_место : boolean;</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp;| Есть_место := Свободная &#60;&#62; 0;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;function Пуста (номер_очереди: integer): boolean;</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp;| Пуста := Первый [номер_очереди] = 0;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;procedure Взять (var t: T; номер_очереди: integer);</div><div class="code_line">&nbsp;&nbsp;| var перв: integer;</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp;| {not Пуста (номер_очереди)}</div><div class="code_line">&nbsp;&nbsp;| перв := Первый [номер_очереди];</div><div class="code_line">&nbsp;&nbsp;| t := Содержание [перв]</div><div class="code_line">&nbsp;&nbsp;| Первый [номер_очереди] := Следующий [перв];</div><div class="code_line">&nbsp;&nbsp;| Следующий [перв] := Свободная;</div><div class="code_line">&nbsp;&nbsp;| Свободная := перв;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;procedure Добавить (t: T; номер_очереди: integer);</div><div class="code_line">&nbsp;&nbsp;| var нов, посл: 1..n;</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp;| {Есть_место }</div><div class="code_line">&nbsp;&nbsp;| нов := Свободная; Свободная := Следующий [Свободная];</div><div class="code_line">&nbsp;&nbsp;| {из списка свободного места изъят номер нов}</div><div class="code_line">&nbsp;&nbsp;| if Пуста (номер_очереди) then begin</div><div class="code_line">&nbsp;&nbsp;| | Первый [номер_очереди] := нов;</div><div class="code_line">&nbsp;&nbsp;| | Последний [номер_очереди] := нов;</div><div class="code_line">&nbsp;&nbsp;| | Следующий [нов] := 0;</div><div class="code_line">&nbsp;&nbsp;| | Содержание [нов] := t;</div><div class="code_line">&nbsp;&nbsp;| end else begin</div><div class="code_line">&nbsp;&nbsp;| | посл := Последний [номер_очереди];</div><div class="code_line">&nbsp;&nbsp;| | {Следующий [посл] = 0 }</div><div class="code_line">&nbsp;&nbsp;| | Следующий [посл] := нов;</div><div class="code_line">&nbsp;&nbsp;| | Следующий [нов] := 0;</div><div class="code_line">&nbsp;&nbsp;| | Содержание [нов] := t</div><div class="code_line">&nbsp;&nbsp;| | Последний [номер_очереди] := нов;</div><div class="code_line">&nbsp;&nbsp;| end;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;function Очередной (номер_очереди: integer): T;</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp;| Очередной := Содержание [Первый [номер_очереди]];</div><div class="code_line">&nbsp;&nbsp;end;</div></ol></div></div></div></div><br>
<br>
<strong class='tag-b'>2.9.</strong> Та же задача для деков вместо очередей.<br>
<br>
<span class='tag-u'>Указание</span><br>
Дек - структура симметричная, поэтому надо хранить ссылки в обе стороны (вперед и назад). При этом удобно к каждому деку добавить фиктивный элемент, замкнув его в кольцо, и точно такое же кольцо образовать из свободных позиций.<br>
<br>
В следующей задаче дек используется для хранения вершин выпуклого многоугольника.<br>
<br>
<strong class='tag-b'>2.10. </strong> На плоскости задано n точек, пронумерованных слева направо (а при равных абсциссах - снизу вверх). Составить программу, которая строит многоугольник, являющийся их выпуклой оболочкой, за не более чем C*n действий.<br>
<br>
<span class='tag-u'>Решение.</span><br>
Будем присоединять точки к выпуклой оболочке одна за другой. Легко показать, что последняя присоединенная точка будет одной из вершин выпуклой оболочки. Эту вершину мы будем называть выделенной. Очередная присоединяемая точка видна из выделенной (почему?). Дополним наш многоугольник, выпустив из выделенной вершины &quot;иглу&quot;, ведущую в присоединяемую  точку. Получится вырожденный многоугольник, и остается ликвидировать в нем &quot;впуклости&quot;.<br>
<br>
Будем хранить вершины многоугольника в деке в порядке обхода его периметра по часовой стрелке. При этом выделенная вершина является началом и концом (головой и хвостом) дека. Присоединение &quot;иглы&quot; теперь состоит в добавлении присоединяемой вершины в голову и в хвост дека. Устранение &quot;впуклостей&quot; несколько более сложно. Назовем подхвостом и подподхвостом элементы дека, стоящие за его хвостом. Устранение впуклости у хвоста делается так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp;while по дороге из хвоста в подподхвост &nbsp;мы поворачиваем</div><div class="code_line">&nbsp;&nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;у подхвоста влево (&quot;впуклость&quot;) do begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;| выкинуть подхвост из дека</div><div class="code_line">&nbsp;&nbsp; &nbsp;end</div></ol></div></div></div></div><br>
Таким же способом устраняется &quot;впуклость&quot; у головы дека.<br>
<br>
<span class='tag-u'>Замечание</span><br>
Действия с подхвостом и подподхвостом не входят в определение дека, однако сводятся к небольшому числу манипуляций<br>
с деком (надо забрать три элемента с хвоста, сделать что надо и вернуть).<br>
<br>
<span class='tag-u'>Ещё одно замечание</span><br>
Есть два вырожденных случая: если мы вообще не поворачиваем у подхвоста (т.е. три соседние вершины лежат на одной прямой) и если мы поворачиваем на 180 градусов (так бывает,  если наш многоугольник есть двуугольник). В первом случае подхвост стоит удалить (чтобы в выпуклой оболочке не было лишних вершин), а во втором случае - обязательно оставить.]]></description>
        <author>Krishkinn</author>
        <category>Pascal: Структуры данных</category>
      </item>
	
      </channel>
      </rss>
	