> Т.е. исходный алгоритм на Си на пару писем раньше тоже был запутанным

Спасибо, Александр!  Подтверждаю.  Во всем виноват я.  Написал очень
запутанную процедуру.  Допишу имейл и предприму самобичевание плетью
с крючками.

> А все-таки на следующей странице оно понятнее (функция siftDown)

Конечно!  Удваивание количества используемых переменных, выход из
двух мест вместо одного и многократное подталкивание значения мелкимми
шажками (вместо того, чтобы найти его место и поставить раз) – все это
чрезвычайно способствует ясности.

> А чтобы добиться структурности вам приходится ...

Хотите — верьте, хотите — нет, но я не стремился к структурности
и в принципе не стремлюсь, так как мне и непонятен смысл слова в
контексте программ.  Многолетное и чтение литературы, и собственная
практика не помогли в этом.  А стремлюсь к тому, чтобы текст отвечал
смыслу того, что я хочу выразить и, по возможности, не было лишних
имен, действий и прочих сущностей.  Что, конечно, глубоко ошибочно
с моей стороны.

> Да к тому же обеспечить доступ в теле цикла к вычисленному внутри условий 
> индексу j, объявив j вне цикла.

j можно спокойно объявить в начале цикла, если так больше нравится.
От этого доступность не пострадает, а j используется в каждой
строке цикла.

> Стало, конечно, структурно, но более запутанно.

Как уже сказал, что такое «структурно» и чем оно полезно я понятия не
имею.  А насчет «запутанно» я уже согласился устами и обеими руками.

Чтобы хоть немного прояснить непроглядный мрак запутанности, приведу
перевод содержания цикла — т.е. практически всей процедуры — с Си на
русском, строка за строкой.  Читаем строго последовательно, слева
направо.

if (j=2*p+1, j+1<n && a[j]<a[j+1])  ++j;
Пусть наш наследник — левый; если имеется правый и он больше левого,
пусть он будет наследником.

if (j>=n || a[j]<=x)  break;
Если наследник за пределом массива или он мал, выходим из цикла.

a[p] = a[j];  p = j;
Поднимаем к себе наследника.  Занимаем его место.

Ответить