Как отобразить на сайте содержимое DOC, RTF, PDF или ODT файла

Google Docs предоставляет возможность встраивать свой вьювер на любые страницы, с помощью iframe:

Пример просмотра файла http://example.com/file.pdf:

<iframe
    src="http://docs.google.com/gview?url=http://example.com/file.pdf&embedded=true"
    style="width:600px; height:500px;"
    frameborder="0"
></iframe>

Поддерживаемые форматы — PDF, DOC, RTF и ODT.

Добавлено: 29 Июля 2018 22:28:29 Добавил: Андрей Ковальчук

Как получить скриншоты видео залитого на YouTube

У каждого видео, залитого на YouTube, есть 4 скриншота хранящихся на серверах самого YouTube. Один скриншот имеет размер 480x360, а три других — 120x90. Скриншоты доступны по адресу:

http://img.youtube.com/vi/[VIDEO_ID]/[0-3].jpg
Например для http://www.youtube.com/watch?v=rF1X12PE6PY это:

http://img.youtube.com/vi/rF1X12PE6PY/0.jpg
http://img.youtube.com/vi/rF1X12PE6PY/1.jpg
http://img.youtube.com/vi/rF1X12PE6PY/2.jpg
http://img.youtube.com/vi/rF1X12PE6PY/3.jpg

Добавлено: 29 Июля 2018 20:33:08 Добавил: Андрей Ковальчук

Мой подход к работе с Git

Второй день знакомлюсь с Git. Читаю книжку Pro Git, попутно загоняя буковки в консоль =)

Расскажу, как организовал процесс разработки на своём компьютере. Если что-то не правильно или есть лучшие способы, то смело пишите в комментах!

Более опытные коллеги подсказали, что ставить на локальный компьютер "Git сервер" не очень разумно, лучше обойтись одной папкой в которой будут размещаться голые (bare) репозитории и которая будет служить центральным хранилищем.

Итак. Создаём папку под голые репозитории, например C:\GitRepos (да да, я сижу на Windows):

$ mkdir /c/GitRepos

Создаём голый репозиторий myproject.git:

$ cd /c/GitRepos
$ mkdir myproject.git
$ cd myproject.git
$ git init --bare

Переходим в каталог, в котором располагаются исходники проекта myproject и создаём там новый локальный репозиторий:

$ git init

Связываем его с основным:

$ git remote add origin /c/GitRepos/myproject.git

Добавляем в локальный репозиторий файлы и делаем первый коммит:

$ git add .
$ git commit -a -m 'First commit'

Отправляем проект на "сервер" (в папку C:\GitRepos):

$ git push origin master

Теперь чтобы продолжить разработку myproject в другом месте, нужно сделать копию основного репозитория:

$ git clone /c/GitRepos/myproject.git

и после очередного коммита в локальный репозиторий, обновить основной:

$ git push

Получить свежую версию из основного репозитория, можно так:

$ git pull

Добавлено: 27 Июля 2018 22:52:42 Добавил: Андрей Ковальчук

Присваивание рангов

Задача
Вы хотите присвоить ранги набору значений.

Решение
Выберите метод ранжирования, расположите элементы в нужном порядке и примените к ним выбранный метод.

Обсуждение
Для некоторых типов статистических проверок требуется присваивание рангов. Я опишу три метода ранжирования и покажу, как можно реализовать каждый из них при помощи переменных SQL. В примерах предполагается, что таблица t содержит следующие результаты, которые должны быть ранжированы по убыванию значений:

mysql> SELECT score FROM t ORDER BY score DESC;

+-------+
| score |
+-------+
| 5 |
| 4 |
| 4 |
| 3 |
| 2 |
| 2 |
| 2 |
| 1 |
+-------+

Один из способов ранжирования заключается просто в присвоении каждому значению номера соответствующей строки упорядоченного множества значений. Для получения такой классификации будем отслеживать номер строки и использовать его для текущего ранга:

mysql> SET @rownum := 0;
mysql> SELECT @rownum := @rownum + 1 AS rank, score
-> FROM t ORDER BY score DESC;


+-----+-------+
| rank | score |
+-----+-------+
| 1 | 5 |
| 2 | 4 |
| 3 | 4 |
| 4 | 3 |
| 5 | 2 |
| 6 | 2 |
| 7 | 2 |
| 8 | 1 |
+-----+-------+

Такая классификация не принимает в расчет возможность «ничейного счета» – вхождения одинаковых значений. Второй метод учитывает такую возможность, увеличивая ранг только при изменении значения:

mysql> SET @rank = 0, @prev_val = NULL;
mysql> SELECT @rank := IF(@prev_val=score,@rank,@rank+1) AS rank,
-> @prev_val := score AS score
-> FROM t ORDER BY score DESC;


+-----+-------+
| rank | score |
+-----+-------+
| 1 | 5 |
| 2 | 4 |
| 2 | 4 |
| 3 | 3 |
| 4 | 2 |
| 4 | 2 |
| 4 | 2 |
| 5 | 1 |
+-----+-------+

Третий метод ранжирования – это комбинация первых двух. Ранги присваиваются по номеру строки, за исключением случаев с повторениями. Все одинаковые значения получают одинаковый ранг, равный номеру строки первого из значений. Для реализации этого метода будем отслеживать номер строки и предыдущее значение, увеличивая ранг до текущего номера строки при изменении значения:

mysql> SET @rownum = 0, @rank = 0, @prev_val = NULL;
mysql> SELECT @rownum := @rownum + 1 AS row,
-> @rank := IF(@prev_val!=score,@rownum,@rank) AS rank,
-> @prev_val := score AS score
-> FROM t ORDER BY score DESC;


+-----+------+-------+
| row | rank | score |
+-----+------+-------+
| 1 | 1 | 5 |
| 2 | 2 | 4 |
| 3 | 2 | 4 |
| 4 | 4 | 3 |
| 5 | 5 | 2 |
| 6 | 5 | 2 |
| 7 | 5 | 2 |
| 8 | 8 | 1 |
+-----+------+-------+

Ранги так же легко присваивать и в программах. Например, следующий фрагмент кода PHP ранжирует результаты из таблицы t, используя третий метод:

$result_id = mysql_query ("SELECT score FROM t ORDER BY score DESC", $conn_id)
or die ("Cannot select scores\n");
$rownum = 0;
$rank = 0;
unset ($prev_score);
print ("Row\tRank\tScore\n");
while (list ($score) = mysql_fetch_row ($result_id))
{
++$rownum;
if ($rownum == 1 || $prev_score != $score)
$rank = $rownum;
print ("$rownum\t$rank\t$score\n");
$prev_score = $score;
}
mysql_free_result ($result_id);


Третий способ ранжирования широко распространен вне области статистических расчетов. Вспомните, как в рецепте 3.18 мы использовали таблицу al_winner, содержащую информацию о 15 лучших подающих 2001 года из Американской Лиги :

mysql> SELECT name, wins FROM al_winner ORDER BY wins DESC, name;


+-----------------+------+
| name | wins |
+-----------------+------+
| Mulder, Mark | 21 |
| Clemens, Roger | 20 |
| Moyer, Jamie | 20 |
| Garcia, Freddy | 18 |
| Hudson, Tim | 18 |
| Abbott, Paul | 17 |
| Mays, Joe | 17 |
| Mussina, Mike | 17 |
| Sabathia, C.C. | 17 |
| Zito, Barry | 17 |
| Buehrle, Mark | 16 |
| Milton, Eric | 15 |
| Pettitte, Andy | 15 |
| Radke, Brad | 15 |
| Sele, Aaron | 15 |
+----------------+------+

С помощью третьего метода этим игрокам можно присвоить ранги следующим образом:

mysql> SET @rownum = 0, @rank = 0, @prev_val = NULL;
mysql> SELECT @rownum := @rownum + 1 AS row,
-> @rank := IF(@prev_val!=wins,@rownum,@rank) AS rank,
-> name,
-> @prev_val := wins AS wins
-> FROM al_winner ORDER BY wins DESC;


+-----+------+-----------------+------+
| row | rank | name | wins |
+-----+------+-----------------+------+
| 1 | 1 | Mulder, Mark | 21 |
| 2 | 2 | Clemens, Roger | 20 |
| 3 | 2 | Moyer, Jamie | 20 |
| 4 | 4 | Garcia, Freddy | 18 |
| 5 | 4 | Hudson, Tim | 18 |
| 6 | 6 | Abbott, Paul | 17 |
| 7 | 6 | Mays, Joe | 17 |
| 8 | 6 | Mussina, Mike | 17 |
| 9 | 6 | Sabathia, C.C. | 17 |
| 10 | 6 | Zito, Barry | 17 |
| 11 | 11 | Buehrle, Mark | 16 |
| 12 | 12 | Milton, Eric | 15 |
| 13 | 12 | Pettitte, Andy | 15 |
| 14 | 12 | Radke, Brad | 15 |
| 15 | 12 | Sele, Aaron | 15 |
+----+------+-----------------+------+

Добавлено: 23 Июля 2018 20:37:56 Добавил: Андрей Ковальчук

Добавление свойств в базовый объект

Задача
Необходимо создать объект и добавить в него свойства, но не определяя его формально как отдельный класс. Это удобно, когда нужна функция, требующая объект с определенными свойствами, например такой, который возвращает функция mysql_fetch_object() или функция imap_header().

Решение
Это делается при помощи встроенного базового класса stdClass:

$pickle = new stdClass;
$pickle->type = 'fullsour';


Обсуждение
Точно так же, как функция array() возвращает пустой массив, создание объекта типа stdClass предоставляет объект без свойств и методов.

Как и в случае объектов, принадлежащих другим классам, можно создавать новые свойства объекта, присваивать им значения и проверять эти свойства:

$guss = new stdClass;
$guss->location = 'Essex';
print "$guss->location\n";$guss->location = 'Orchard';
print "$guss->location\n";
Essex
Orchard


Однако после того как создан экземпляр объекта, методы добавлять нельзя.

Создание объекта типа stdClass полезно, когда нужна функция, принимающая базовый объект, такой, который возвращает функция, делающая выборку из базы данных, но вы не хотите посылать запрос в базу данных. Например:

function pc_format_address($obj) {
return "$obj->name <$obj->email>";
}
$sql = "SELECT name, email FROM users WHERE id=$id";
$dbh = mysql_query($sql);
$obj = mysql_fetch_object($dbh);
print pc_format_address($obj);
David Sklar <david@example.com>


Функция pc_print_address() принимает имя и адрес электронной почты и преобразует эти значения в формат, необходимый для полей To и From в почтовой программе. Ниже показано, как вызывать такую функцию, не вызывая функцию mysql_fetch_object():

$obj = new stdClass;
$obj->name = 'Adam Trachtenberg';
$obj->email = 'adam@example.com';
print pc_format_address($obj);
Adam Trachtenberg

Добавлено: 21 Июля 2018 16:17:24 Добавил: Андрей Ковальчук

Разбиение строк

Задача
Необходимо разделить строку на части. Например, нужно получить доступ к каждой из строк, которые пользователь вводит в поле <textarea> формы.

Решение
Если в качестве разделителя частей строк выступает строковая константа, то следует применять функцию explode():

$words = explode(' ','My sentence is not very complicated');


Функция split() или функция preg_split() применяются, если при описании разделителя требуется регулярное выражение POSIX или Perl:

$words = split(' +','This sentence  has  some extra whitespace  in it.');
$words = preg_split('/\d\. /','my day: 1. get up 2. get dressed 3. eat toast');
$lines = preg_split('/[\n\r]+/',$_REQUEST['textarea']);


В случае чувствительного к регистру разделителя применяется функция spliti() или флаг /i в функции preg_split():

$words = spliti(' x ','31 inches x 22 inches X 9 inches');
$words = preg_split('/ x /i','31 inches x 22 inches X 9 inches');


Обсуждение
Простейшим решением из всех приведенных выше является использование explode(). Передайте ей разделитель строки, саму строку, которую необходимо разделить, и в качестве необязательного параметра предельное количество возвращаемых элементов:

$dwarves = 'dopey,sleepy,happy,grumpy,sneezy,bashful,doc';
$dwarf_array = explode(',',$dwarves);


Теперь переменная $dwarf_array – это массив из семи элементов:

print_r($dwarf_array);
Array
(
    [0] => dopey
     => sleepy
     => happy
     => grumpy
     => sneezy
     => bashful
     => doc
)


Если заданный предел меньше количества возможных частей, то последняя часть содержит все остальное:

$dwarf_array = explode(',',$dwarves,5);
print_r($dwarf_array);
Array
(
    [0] => dopey
     => sleepy
     => happy
     => grumpy
     => sneezy,bashful,doc
)


Функция explode() трактует разделитель строки буквально. Если разделитель строки определяется как запятая с пробелом, то данная функция делит строку по пробелу, следующему за запятой, а не по запятой или пробелу. Функция split() предоставляет большую гибкость. Вместо строкового литерала в качестве разделителя она использует регулярное выражение POSIX:

$more_dwarves = 'cheeky,fatso, wonder boy, chunky,growly, groggy, winky';
$more_dwarf_array = split(', ?',$more_dwarves);


Это регулярное выражение разделяет строку по запятой, за которой следует необязательный пробел, что позволяет правильно определить всех новых гномов. Таким образом, пробелы в их именах не разделяют их на части, но каждое имя выделяется независимо от того, отделяется ли оно с помощью запятой «,» или с помощью запятой с пробелом «, »:

print_r($more_dwarf_array);
Array
(
    [0] => cheeky
     => fatso
     => wonder boy
     => chunky
     => growly
     => groggy
     => winky
)


Существует функция preg_split(), которая подобно функции split() использует Perl-совместимые регулярные выражения вместо регулярных выражений POSIX. Функция preg_split() предоставляет преимущества различных расширений регулярных выражений в Perl, а также хитрые приемы, такие как включение текста-разделителя в возвращаемый массив строк:

$math = "3 + 2 / 7 - 9";
$stack = preg_split('/ *([+\-\/*]) */',$math,-1,PREG_SPLIT_DELIM_CAPTURE);
print_r($stack);
Array
(
    [0] => 3
     => +
     => 2
     => /
     => 7
     => -
     => 9
)


Разделитель-регулярное выражение ищет математические операторы (+, -, /, *), окруженные необязательными начальными или завершающими пробелами. Флаг PREG_SPLIT_DELIM_CAPTURE приказывает функции preg_split() включить совпадения как часть разделителя-регулярного выражения, заключенного в кавычки, в возвращаемый строковый массив. В кавычках только символы математических операций, поэтому возвращенный массив не содержит пробелов.

Добавлено: 12 Июля 2018 20:08:31 Добавил: Андрей Ковальчук

Идентификационный код, дата рождения и юзабилити

Читатели блога, проживающие в Украине, конечно, знают, что всем жителям Украины присваивается, так называемый, идентификационный код (ИК). Есть он и у меня. Но совсем недавно я узнал, что это не просто набор из 10 цифр.

Первые пять цифр – это номер дня рождения, начиная с 1 января 1900 года. Т.е. человек, родившийся 1.01.1900 получит код, начинающийся с 00001, 2.01.1900 – 00002, …, 1.01.1901 – 00366 и т.д.

Следующие четыре знака – порядковый номер человека (среди тех, кто родился в один день). Он присваивается по мере поступления информации о людях в центральную базу данных. В этих же четырех знаках заложена информация о поле человека. Она обозначается девятым символом: четное число – женский, нечетное – мужской.

Последний символ – контрольное число. Оно определяется по алгоритму, который не разглашается, дабы усложнить подделку номера.

Таким образом, не составляет труда по ИК определить дату рождения и, наоборот. Вот здесь мы подходим к вопросу о юзабилити. При оформлении кредитов, депозитов и т.д. и т.п. требуется указать и день рождения и ИК. Естественно, эти данные поступают в компьютер. Хорошая программа после ввода ИК автоматически заполнит поле с датой рождения, при вводе даты рождения подставит первые 5 цифр в поле ИК, если оно пустое, или сообщит об ошибке, если код и дата несоответствуют друг другу.

И еще одна история о юзабилити, рассказанная мне несколько лет назад коллегой. Он работал в некоторой фирме, среди сотрудников которой (в основном программистов) была женщина, плохо владеющая компьютером и занимающаяся только вводом в компьютер бумажного словаря. Изо дня в день, слово за словом, она вносила содержимое словаря в, написанную одним из программистов фирмы, для этих целей программу. Однажды программа вывела сообщение, в котором сообщала, что введенное слово неверно. Действительно, оно содержало ошибку, но как простая программа, не имеющая своего словаря догадалась об этом? Оказывается, разработчик программы, зная, что слова будут вноситься последовательно из словаря, сделал проверку на то, чтобы слова шли в алфавитном порядке. Конечно, все ошибки ввода таким образом отсечь невозможно, но, согласитесь, что реализовать такую проверку очень просто, а юзабилити продукта улучшается.

Эти два примера показывают, как небольшой ценой можно увеличить удобство пользования программой и произвести хорошее впечатление на пользователей. Думаю, что вы можете что-то улучшить в ваших программах. Попробуйте.

Добавлено: 17 Мая 2018 20:28:42 Добавил: Андрей Ковальчук

Только CSS сообщение, выпадающее сверху экрана

В данном уроке мы разберемся, как сделать средствами CSS выскакивающее сверху окна браузера сообщение, которое скрывается через определенное время.

Делаем простой div:

<div id="note">
    Текст сообщения будет написан здесь.
</div>

Затем задаем для него стили и помещаем вверх экрана:
#note {
    position: absolute;
    z-index: 101;
    top: 0;
    left: 0;
    right: 0;
    background: #fde073;
    text-align: center;
    line-height: 2.5;
    overflow: hidden;
    -webkit-box-shadow: 0 0 5px black;
    -moz-box-shadow:    0 0 5px black;
    box-shadow:         0 0 5px black;
}

Определим анимацию, которая будет скрывать наше сообщение выше области просмотра и выводить его на короткое время.
@-webkit-keyframes slideDown {
    0%, 100% { -webkit-transform: translateY(-50px); }
    10%, 90% { -webkit-transform: translateY(0px); }
}
@-moz-keyframes slideDown {
    0%, 100% { -moz-transform: translateY(-50px); }
    10%, 90% { -moz-transform: translateY(0px); }
}

Отвлечемся на минуту на те браузеры, которые не поддерживают анимаций и трансформации. Для них сообщение будет выводиться все время с возможностью закрыть его. Будем использовать Modernizr для проверки поддержки анимации и трансформации, а CSS код будет запускать особенный функционал только в случае поддержки его браузером.
.cssanimations.csstransforms #note {
    -webkit-transform: translateY(-50px);
    -webkit-animation: slideDown 2.5s 1.0s 1 ease forwards;
    -moz-transform:    translateY(-50px);
    -moz-animation:    slideDown 2.5s 1.0s 1 ease forwards;
}

Здесь 1.0s задержка перед запуском анимации. Сообщение, которое появляется не сразу, а с задержкой, является более заметным.

Добавим кнопку закрытия в наш код HTML:
<div id="note">
    Текст сообщения будет написан здесь. <a id="close">[закрыть]</a>
</div>

И придется использовать JavaScript, чтобы закрыть сообщение в тех браузерах, которые не поддерживают анимации и трансформации:
<script>
 close = document.getElementById("close");
 close.addEventListener('click', function() {
   note = document.getElementById("note");
   note.style.display = 'none';
 }, false);
</script>

Никаких библиотек не используем. Остается только скрыть кнопку закрытия для поддерживающих анимации браузеров:
.cssanimations.csstransforms #close {
  display: none;
}

Готово!

Добавлено: 16 Мая 2018 17:19:20 Добавил: Андрей Ковальчук

Вложенность

Создание неограниченной вложенности разделов форума, зц, каталога...
Сложно ли это? Конечно же нет! Для этого нам понадобится создать 1 дополнительное поле в таблице с разделами.

Рассмотрим на примере загруз - центра

#PHP
<?php
/* Создадим таблицу */
CREATE TABLE `categories` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`id_cat` int(11) DEFAULT '0' NOT NULL,
PRIMARY KEY (`id`),
KEY `id_cat` (`id_cat`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
/*
id - идентификатор категории
name - названия категории
id_cat - доминирующая категория
*/

Что будет содержать поле id_cat? Ответ: id категории, в которую вложена категория с указанным id.
Создадим небольшой скрипт для вывода категорий:
#PHP
<?php
// главная страница зц(index.php):
$res=mysql_query('SELECT id,name FROM categories WHERE id_cat=0'); // получаем список главных категорий
while($m=mysql_fetch_assoc($res)){ // выводим их в цикле
echo '<a href="cat.php?id='.$m['id'].'">'.$m['name'].'</a><br/>';
}

// страница с выводом списка файлов(cat.php):
if(isset($_GET['id']) and is_numeric($_GET['id'])){ // проверяем, передан ли id скрипту, и является ли он целым числом
$id=intval($_GET['id']);
}else{exit('Неверный id');}

echo 'Путь к категории: '.cat_print($id); // печатаем полный список категорий до указанной категории
// функцию cat_print разберем чуть позже

$res=mysql_query('SELECT id,name FROM categories WHERE id_cat='.$id); // получаем список категорий, у которых id_cat равен переданному id
while($m=mysql_fetch_assoc($res)){ // выводим их в цикле
echo '<a href="cat.php?id='.$m['id'].'">'.$m['name'].'</a><br/>';
}

// если есть в категории файлы, то выводим их ниже списка категорий
echo '<hr />';
$res=mysql_query('SELECT * FROM files WHERE categories='.$id);
while($m=mysql_fetch_assoc($res)){ // вывод списка файлов и категорий, в которых он находится
echo '<a href="file.php?id='.$m['id'].'">'.$m['filename'].'</a> (Категория: '.cat_print($m['categories']).')<br/>';
}

Например, есть 4 категории:
#TEXT
Картинки (id 1, id_cat 0) // эта категория главная
Машинки (id 2, id_cat 1) // эта категория вложена в категорию "Картинки"
Для компов (id 3, id_cat 2) // эта категория вложена в категорию "Машинки"
Для телефонов (id 4, id_cat 2) // эта категория вложена в категорию "Машинки"

С этим разобрались. Едем дальше.
Как нам вывести полный список категорий, в которой находится файл или вложенная категория?
К сожалению, тут не обойтись без рекурсии, т.к. mysql ее не поддерживает.
#PHP
<?php
function cat($id){ // создаем функцию, которая вытащит из базы все категории и подкатегории по переданному ей id
$return=array(); // создаем массив, в который будем записывать категории
$m=mysql_query('SELECT * FROM categories WHERE id='.$id); // вытаскиваем имя категории, для переданного id
if(mysql_num_rows($m)){ // проверяем, есть ли она в базе
$m=mysql_fetch_assoc($m); // если есть, создаем массив
$return[]=array($m['id'],$m['name']); // заносим в массив id категории как ключ массива,и имя категории как значение массива
if($m['id_cat']){ // проверяем, есть ли у категории доминирующие категории
$return=array_merge($return,cat($m['id_cat'])); // если есть, то запускаем функцию заново, но уже с id домирующей категории, и полученный результат соединяем с уже имеющимся
}
}

return $return;
}


function cat_print($id){ // основная функция, которую мы будем применять
$print=cat($id); // получаем список категорий в виде массва
$print=array_reverse($print); // переворачиваем массив, чтобы категории выводились начиная с главных
for($i=0,$s=sizeof($print);$i<$s;$i++){ // выводим их в цикле
echo '<a href="cat.php?id='.$print[$i][0].'">'.$print[$i][1].'</a>/';
}
}

Ну вот и все, дальше сами, своим ходом, юзайте на здоровье :)

Добавлено: 16 Мая 2018 14:51:34 Добавил: Андрей Ковальчук

Директива safe_mode = on, mkdir и решение проблем создания папок на сервере

В PHP есть единственная функция – mkdir(), которая позволяет создавать на сервере сайта директории, которые порой так необходимы в хозяйстве. Например, при создании нового материала вам необходимо создать под него папку, куда опять же средствами вашей CMS вы будете заливать все необходимые файлы.

Пример:

mkdir("/path/to/my/dir", 0700);

Т.е. в определенной директории мы создаем новую папку и например задаем ей режим mode 0700, например для того, чтобы в папку можно было записывать файлы режим mode меняем на 0777.

Но вот тут то и возникает проблема с mkdir(). При выполнении этого php скрипта при включенной функции сервера safe_mode происходит проверка владельца (UID) и если не совпадает владелец скрипта и папки, то возможно вы не сможете, например, записать файл в созданную директорию, удалить файл в ней или, например через FTP у вас не получится удалить саму папку.

Но есть более изящное решение этой проблемы, без необходимости просить хостера отключать вам функцию safe_mode (данная функция включена абсолютно на всех хостингах по умолчанию, с целью обеспечения безопасности). В основе своей платные хостинги предоставляют и доступ к ftp, именно от этого мы и будем отталкиваться.
$conn_ftp = @ftp_connect('your_ftp_server', 21, 5);

Первая переменная в функции это адрес вашего ftp сервера, вторая порт, по которому вы соединяетесь с ftp и последняя это допустимый таймаут соединения. Немного о таймауте, он необходим для последующих сетевых операций, если его не вводить, то ставится значение по умолчанию, равное 90 секундам. После соединения мы проверяем прошло ли оно успешно и отправляем логин и пароль:
if($conn_ftp) // соединение прошло успешно
{
    $login_result = @ftp_login($conn_ftp, 'user', 'pass'); // вводим свои логин и пароль для FTP
    if($login_result) // проверка логина и пароля прошла успешно
    {
        ftp_pasv ($conn_ftp, TRUE);
    }
}

После проверки логина и пароля нам необходимо определиться с пассивным режимом и выставить ему значения TRUE или FALSE - это необходимо если дальнейшие функции FTP будут работать неправильно. Теперь после определения пассивного режима мы можем создавать наши папки, я опишу все функции которые могут пригодиться вам в дальнейшем:
$file = ftp_mkdir ($conn_ftp, 'public_html/materials/345');
//Создание директории 345 в папке materials, если папки materials не существует,
//то она так же будет создана, так же и с папкой public_html (данная директория
//указана для того, чтобы вы видели весь путь, а так это просто папка с сайтом)
 
ftp_chdir ($conn_ftp, 'public_html/materials');
//Если у вас точно есть папка materials, то вам не обязательно прописывать весь
//путь, можно просто сначала в нее перейти и потом в ней создать папку 345 используя
//следующий код ftp_mkdir ($conn_ftp, '345')
 
ftp_chmod($conn_ftp, 0777, $file);
//Все папки по умолчанию создаются с режимом mode 0755, данная команда позволит сменить
//его на 0777, что позволит вам заносить файлы в созданную папку.

Теперь приведу полный пример рабочего кода, чтобы вы увидели как все это выглядит, например у меня:
$dir_name = time(); //Здесь я создаю имя папки по времени запуска скрипта
$conn_ftp = @ftp_connect('your_ftp_server', 21, 5);
if($conn_ftp) // соединение прошло успешно
{
    $login_result = @ftp_login($conn_ftp, 'user', 'pass'); // вводим свои логин и пароль для FTP
    if($login_result) // проверка логина и пароля прошла успешно
    {
        ftp_pasv ($conn_ftp, TRUE);
        ftp_chdir ($conn_ftp, 'public_html/materials');
        ftp_mkdir ($conn_ftp, $dir_name);
        ftp_chmod($conn_ftp, 0777, $dir_name);
    }
}

Стоит еще сказать немного об указании директорий при создании, если вы укажете в начале слэш, то папка будет создаваться относительно корня ftp. При подключении к серверу FTP вы всегда подключаетесь к корню, поэтому учтите этот момент.

Добавлено: 16 Мая 2018 14:46:33 Добавил: Андрей Ковальчук

Хотите использовать JSON, но не знаете с чего начать?

JSON является частью стандарта ECMAScript начиная с 1999 года, когда ECMA определила функцию eval() воспринимающую формат. Он стал набирать популярность вместе с нарастающим успехом Ajax. Слово JSON часто появляется когда кто-нибудь заводит речь об Ajax. Известно, что JSON является другим форматом данных, что он замещает XML, и что многие программисты активно поддерживают его. Но что такое в действительности JSON и в чем его преимущества?

Почему JSON?
Преимущество JSON заключается в том, что он распознается в JavaScript. Нет необходимости разбирать документ, как это происходит с XML, для передачи данных через интернет.

JSON и XML
Преимущества JSON:

Простой для чтения и понимания.
Простой для использования.
Преимущества XML:

Имеет возможности расширения
И XML и JSON имеют возможность интегрировать большой объем данных в бинарной форме.

Синтаксис JSON
Компоненты JSON:

Объекты: содержат объекты или атрибуты.
Скалярные переменные: число, строка, логическая переменная.
Массив.
Литеральные значения: null, true, false, "строка символов", и числовые значения.
Объект
Содержит элемент или список элементов, где каждый элемент описывается следующим образом:

"имя" : "значение"

Синтаксис объекта:

{ элемент, элемент, .... }

Массив
Набор значений, разделенных запятой.

[ значение, значение, ....]

Значение
Значение может быть: объектом, массивом, литеральным значением (строка, число, true, false, null).

Для создания JSON файла больше ничего не нужно!

Пример JSON файла
Простой пример структура меню. В данном объекте содержатся атрибуты и массив, который включает другие объекты строки меню.

{
  "menu": "Файл",
  "commands": [
      {
          "title": "Новый",
          "action":"CreateDoc"
      },
      {
          "title": "Открыть",
          "action": "OpenDoc"
      },
      {
          "title": "Закрыть",
          "action": "CloseDoc"
      }
   ]
}

Эквивалент на XML:
<?xml version="1.0" ?>
<root>
<menu>Файл</menu>
<commands>
<item>
<title>Новый</value>
<action>CreateDoc</action>
</item>
<item>
<title>Открыть</value>
<action>OpenDoc</action>
</item>
<item>
<title>Закрыть</value>
<action>CloseDoc</action>
</item>
</commands>
</root>

Как использовать формат
Файл JSON позволяет загружать данные с сервера или на сервер. Например, сохранение содержимого формы, которая была только что заполнена пользователем. Процесс включает три фазы: обработку браузером, обработку сервером, и обмен данными между ними.

Клиентская часть (браузер)
Данная часть выполняется достаточно просто, так как JSON является частью определения JavaScript. Содержимое файла или определяющих данных назначается переменным и они становятся объектами программы.

Серверная часть
Файл JSON используется различными программными языками, включая PHP и Java , благодаря наличию парсеров, которые позволяют получать содержимое и даже конвертировать его в классы и атрибуты языка. На сайте JSON можно найти парсеры для многих языков программирования.

Обмен данными
Загрузка файла может быть выполнена в JavaScript несколькими способами:

непосредственное включение файла в HTML страницу как внешний JavaScript файл .js.
загрузка с помощью команды JavaScript.
с использованием XMLHttpRequest.
Файл JSON обрабатывается функцией JavaScript eval(). Отправка файла на сервер может быть выполнена с помощью XMLHttpRequest. Файл отправляется как текстовый и обрабатывается парсером языка программирования, который используется на сервере.

Пример
Код XMLHttpRequest:

var req = new XMLHttpRequest();
req.open("GET", "file.json", true);
req.onreadystatechange = myCode;   // обработчик
req.send(null);
Обработчик JavaScript:

function myCode()
{
   if (req.readyState == 4)
   {
        var doc = eval('(' + req.responseText + ')');
   }
}

Использование данных:
var menuName = document.getElementById('jsmenu');   // ищем поле
menuName.value = doc.menu.value;           // назначаем значение полю

Как получать данные:
doc.commands[0].title      // читаем значение поля "title" в массиве
doc.commands[0].action     // читаем значение поля "action" в массиве

Добавлено: 16 Апреля 2018 21:04:19 Добавил: Андрей Ковальчук

Пять способов ускорить время загрузки страниц

Один из самых важных аспектов вашего сайта – это скорость его загрузки; пользователи хотят мгновенно получать картинку без всяких тормозов, и если вы не в состоянии дать им это, то они долго не раздумывая, поищут информацию в другом месте. В этой статье мы обсудим 5 способов, которые позволят вам ускорить время загрузки вашего сайта.

1. Используйте YSlow для отслеживания времени загрузки страниц
Зная количество времени, которое тратится на загрузку страниц, вы сможете определить проблемные места. Также это придаст вам ещё один стимул, для того чтобы залезть в функционал и постараться исправить ситуацию.

Перед тем как мы начнём, вам необходимо установить YSlow, если вы уже конечно этого не сделали. YSlow - это расширение к Mozilla Firefox, которое вы сможете найти на этой странице:

https://addons.mozilla.org/en-US/firefox/addon/5369

Теперь давайте откроем какой-то сайт. Допустим Six Revisions, для того чтобы данные у нас были примерно одни и те же (просто откройте данный сайт в новой вкладке вашего браузера).

В нижней правой стороне вашего браузера, у вас находится специальная панель с иконкой (смотрите рисунок 1). Чуть поодаль данной панели, после загрузки страницы, рядом с ‘YSlow’ вы увидите число. Данное число – это время загрузки данной страницы в секундах в вашем браузере. Нам необходимо, чтобы данное число было как можно меньше.

Самыми часто встречаемыми «тормозилами» являются следующие объекты или операции:

Слишком много HTTP запросов
Не сжатые файлы JavaScript
Отсутствие времени истечения заголовков для графических файлов
Через несколько минут мы подробнее на этом остановимся.

Для того чтобы освоиться в этой системе, пройдитесь по нескольким сайтам и посмотрите время их загрузки. Можете протестировать сайты Google, Facebook, и парочку ваших любимых блогов/сайтов, где вы чаще всего бываете. Обратите внимание, что больше всего на скорость влияют JavaScript файлы и изображения.

Используем YSlow на полную
Помимо того что YSlow вычисляет время загрузки страницы, данное расширение также предоставляет вам расширенную информацию о том, что вам необходимо исправить для оптимизации загрузки вашего сайта, таким образом, вы сможете подлатать дыры.

Для получения подобной информации нажмите на вкладку Performance. После сканирования сайта, YSlow выдаст вам общую оценку, которая будет характеризовать производительность вашей страницы.

Доступ к информации можно ускорить с помощью CDN (сеть доставки контента). CDN лучше использовать для крупных сайтов. Используются они для того чтобы распределять информацию через несколько серверов в разных частях мира. Таким образом, информация будет загружаться с соответствующего сервера (который ближе всего к пользователю), чтобы не проходить через личные маршрутизаторы. YSlow также отслеживает запросы CDN.

Но люди, как правило, не используют CDN (что является довольно-таки дорогим удовольствием).

Классификация типов ошибок
Теперь давайте пройдёмся по каждому пункту, которые есть в выше упомянутом расширении. Далее вы найдёте краткое содержание того, по каким критериям оцениваются ваши страницы и пути решения проблем для достижения максимальной производительности.

Делайте как можно меньше HTTP запросов: HTTP запрос происходит, когда браузер посылает запрос на сервер. То же самое может происходить при подключении скриптов, файлов CSS, изображений, а также при асинхронных запросах, как со стороны клиента, так и со стороны сервера (Ajax и другие подобные технологии). Однако когда речь заходит о производительности системы, то стоит задуматься о том, сколько подобных запросов происходит у вас на странице. В качестве решения можно применить кэширование, чтобы помочь клиентским машинам быстрее подгружать скрипты, CSS и изображения.

Добавление заголовков Expires: 80% загрузки страницы ориентировано на скачивание скриптов, фотографии и файлов CSS. В большинстве случаев данные вещи не меняются на пользовательских машинах. Добавив немного коду в ваш файл .htaccess, вы можете кэшировать дублирующийся файлы на локальной машине пользователя (о том, как это сделать мы поговорим позже).

Компоненты Gzip: Применение Gzip или сжатие JS файлов, изображений, HTML документов, CSS файлов, и т.д. позволяет пользователям скачивать информацию в уменьшенном размере, что значительно увеличивает скорость загрузки страниц. К тому же это позволит сохранить место на сервере, однако распаковка данных может привести к торможению ответа, и напрямую зависит от браузера пользователя.

Располагайте CSS в верхней части страницы: если вы располагаете подключение к CSS файлам в верхней части страницы, то это значит, что они будут загружаться в первую очередь, а изображения и скрипты позже.

Размещайте JS в нижней части страницы: теперь, когда ваши CSS файлы будут загружаться вверху, самое время расположить скрипты JS прямо перед закрытием тега . Это позволит вашей странице отобразиться, а затем подключить необходимые скрипты.

Избегайте CSS выражений: я лично никогда не использовал CSS выражения (ещё их называют динамическими свойствами). Данные выражения являются собственной концепцией программирования для IE (такие как условные выражения) в CSS. Технология, которая используется в IE8, да и во всех остальных версиях больше поддерживаться не будет, так что в любом случае придётся завязывать с данным написанием CSS выражений. PHP больше подходит для подобных целей, к примеру, для того, чтобы загрузить разные CSS стили в зависимости от какого-то условия, такого как случайное число, время суток или браузер пользователя.

Пишите JS и CSS в отдельных файлах: если вы располагаете ваши скрипты в JS и стили CSS в отдельных файлах, то браузер с лёгкостью сможет их закэшировать, тем самым в последующем позволит вашей странице грузиться быстрее.

Сокращайте время DNS поиска: когда пользователь набирает имя вашего сайта в строке браузера, то тут же начинается DNS поиск IP адреса, по которому находится ваш сайт. Чем больше ваш сайт содержит внешних источников, тем больше будет занимать время DNS поиск. Как правило, один такой поиск длится 60-100 миллисекунд.

Минимизируйте JS: помимо сжатия посредством gzip, минимизация JavaScript файлов позволит вам облегчить скрипты, избавившись от ненужных пробелов, табов, и других специальных знаков, которые в совокупности увеличивают размеры файлов. Это же очевидно – чем меньше файлы, тем быстрее грузятся страницы. Для минимизирования JavaScript файлов можете использовать инструмент JSMIN.

Избегайте перенаправления: не имеет никакого значения, где вы делаете перенаправление, в JS, HTML или PHP. В любом случае ваш браузер получит заголовок с пустой страницей, на загрузку которой потребуется время. Так что просто старайтесь не применять редирект там, где его можно избежать.

Избегайте дублирования загрузки скриптов: если ваш браузер загружает скрипт более одного раза, это значительно сказывается на загрузке страницы. Математика тут не сложная. Чем больше загрузок одних и тех же файлов, тем дольше загрузка страницы. Просмотрите ваши скрипты и убедитесь, что вы не вызываете jQuery 2 или 3 раза. То же самое относится и к скриптам JS.

Что же… думаю этого достаточно. Теперь давайте перейдём к следующей вкладке YSlow, перед тем как рассмотрим некоторые другие техники, которые позволят увеличить скорость загрузки ваших страниц.

Вкладка Components позволит вам определить, какие нужно приложить усилия для улучшения скорости загрузки. Тут вы найдёте информацию о том, сколько весит каждый файл, а также сколько времени ему требуется на загрузку. Также вы сможете увидеть, для каких файлов применяется gzip, узнаете время ответа, а также являются ли файлы закэшированными на пользовательской машине, и когда заканчивается сам кэш. Эта информация может вам пригодиться при оценке проблем вашего сайта, вы будете знать, что у вас не так, и что нужно оптимизировать.

И наконец, перейдём к последней вкладке Stats tab. Тут вы найдёте информацию обо всех HTTP запросах, как для обычных файлов, так и для закэшированных. Значение Empty cache показывает, что данные файлы необходимо загрузить для отображения страницы. В свою очередь Primed Cache - это файлы, которые уже были закэшированы браузером пользователя. Это означает, что их скачивать не нужно.

2. Используйте CSS спрайты для сокращения HTTP запросов
CSS спрайты - это наверное самая значительная вещь, которую придумало человечество, после того как Тесла изобрёл электричество… Я действительно это сказал.. ой, я имел в виду Эдисона.

Ну, может быть не совсем самая крутая, но тем не менее.

CSS спрайты могут помочь значительно увеличить скорость загрузки страницы, сократив количество HTTP запросов, которые формируются для загрузки изображений.

Вы можете найти множество уроков, в которых говорится о том, что CSS спрайты удобны для навигации – в общем, для использования их в пользовательском интерфейсе.

Теперь давайте быстренько посмотрим, как на YouTube используют CSS спрайты. Так выглядит спрайт, которым они пользуются:

YouTube использует этот файл довольно оригинально. Загружают они его как фон классу sprite. Когда возникает необходимость в выборе какого-то элемента, происходит выбор изначальной позиции при помощи CSS свойства background-position, а затем применение высоты и ширины.

Давайте и мы попробуем что-то подобное. Поэкспериментируем на этом же самом изображении с сайта YouTube.

В примере, который расположен ниже, мы выводим логотип YouTube на экран. Используя тот же класс sprite, и то же самое изображение image, мы можем создать изображение, которое будет изменяться при наведении мышки.


<style>
.sprite {
background:url(http://s.ytimg.com/yt/img/master-vfl87445.png);
}

#logo {
width:100px;
height:45px;
background-position:0 0;
}
</style>

<div id="logo" class="sprite"> </div>
Таким образом, используя данное изображение, мы можем свести все подключения к одному HTTP запросу. Ну, как эффект?

Ещё одно преимущество CSS спрайтов заключается в том, что при применении псевдо класса :hover, изображение не будет пропадать на несколько мгновений (которые уходят на загрузку нового изображения), как это происходит без использования CSS спрайтов.


<style>
.sprite {
  background:url(http://s.ytimg.com/yt/img/master-vfl87445.png);
}

#logo {
  width:100px;
  height:45px;
  background-position:0 0;
}

#button {
  background-position:0 -355px;
  padding:5px 8px;
}

#button:hover{
  background-position:-25px -355px;
}

</style>

<div id="logo" class="sprite"> </div>

<a href="#" id="button" class="sprite"></a>

3. Загружайте CSS файлы в начале, JavaScript в конце
Для некоторых сайтов, урезание количества HTTP запросов может привести к нарушению функциональности. Ещё один способ увеличить скорость загрузки страниц - это поместить все подключения к JavaScript файлам в конец документа.

Стоит также отметить:

Загружайте файлы CSS в разделе прямо перед началом тега body.
Подключайте JavaScript перед самым закрытием тега body.
Если вы будете следовать нашему совету, то позволите вашим пользователям любоваться вашим сайтов, в то время как на втором плане будет происходить загрузка ваших JavaScript скриптов.

Примечание: Если вы не хотите перемещать теги JavaScript, потому что боитесь, что падёт функциональность, то я рекомендую вам использовать свойство defer. Применяйте его следующим образом:


<script defer='defer'>

4. Используйте поддомены для параллельного скачивания
Параллельная загрузка означает увеличение параллельных загрузок одних и тех же файлов. Пройдясь по множеству сайтов, вы можете заметить, что на многих из них запросы посылаются на static.domain.com и c1.domain.com. Это можно увидеть в нижней панели браузера.

Это отличный способ увеличить производительность сайта. При использовании поддоменов, по сути, информация будет находиться на одном и том же сервере, однако для браузера они будут разными.

Настройка процесса:

Создайте 3 поддомена на вашем сервере
Расположите ваши изображения в папках на разных поддоменах
Замените пути в ваших файлах
5. Добавление заголовков Expires
Некоторые сайты остаются нагруженными даже после применения всех методов, описанных выше. Но есть ещё пару методов.

Пользователь может зайти на ваш сайт и совершить все необходимые HTTP запросы для отображения страницы, изображений, скриптов и т.д.

Когда вы используете заголовки Expires, вы можете закэшировать все эти элементы на пользовательской машине, тем самым не только увеличив скорость загрузки страницы, а ещё и сократив трафик. Заголовки Expires могут быть применены ко всем вашим скриптам, CSS и изображениям.

Данного эффекта можно добиться посредством нескольких строк, которые вам нужно добавить в файл .htaccess, который находится в корневом каталоге вашего сайта.

Следующий пример .htaccess файла устанавливает заголовки expires на какое-то число в 2010 году для таких типов файлов как .ico, .pfd, .flv (файлы Flash), .jpg, .png, etc.


<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|CSS|swf)$">

  Header set Expires "Thu, 15 Apr 2010 20:00:00 GMT"

</FilesMatch>

Будьте бдительны: если вы произведёте какое-либо изменение в данных файлах (в случае, если срок ещё не прошёл), то вам необходимо переименовать их (или добавить в название версию), иначе в кэше они не обновятся.

К примеру, если у вас есть файл JavaScript, в котором вы что-то изменили, просто добавьте в название номер версии (что-то типа javascriptfile-1.0.js, javascriptfile-1.1.js и т.д.)

Вывод
Сегодня мы прошлись по многим способам. Надеюсь, вы отметили для себя несколько методов, которые будете активно применять в ваших проектах! Удачи!

Добавлено: 15 Апреля 2018 18:58:46 Добавил: Андрей Ковальчук

Примеры реализации сортировки слиянием

C++

               /**
                * @brief         Сортировка элементов от l до r массива buf
                * @param[in/out] buf - сортируемый массив
                * @param[in]     l - левая граница. При первой итерации l = 0
                * @param[in]     r - правая граница. При первой итерации r = buf.size() - 1
                *
                * В результате сортируются все элементы массива buf от l до r включительно.
                */
               template<typename Type>
void MergeSort(vector<Type>& buf, size_t l, size_t r)
{
    //! Условие выхода из рекурсии
    if(l >= r) return;
 
    size_t m = (l + r) / 2;
 
    //! Рекурсивная сортировка полученных массивов
    MergeSort(buf, l, m);
    MergeSort(buf, m+1, r);
    merge(buf, l, r, m);
}
 
/**
 * @brief Слияние элементов.
 * @param[in/out] buf - массив
 * @param[in]     l - левая граница. При певой итерации l = 0
 * @param[in]     r - правая граница. При первой итерации r = buf.size() - 1
 * @param[in]     m - граница подмассивов.
 *
 * Массив buf содержит два отсортированных подмассива:
 * - [l; m] - первый отсортированный подмассив.
 * - [m+1; r] - второй отсортированный подмассив.
 * В результате получаем отсортированный массив, полученный из двух подмассивов,
 * который сохраняется в buf[l; r].
 */
template<typename Type>
static void merge(vector<Type>& buf, size_t l, size_t r, size_t m)
{
    if(l >= r || m < l || m > r) return;
    if(r == l + 1 && buf[l] > buf[r])
    {
        swap(buf[l], buf[r]);
        return;
    }
 
    vector<Type> tmp(&buf[l], &buf[r+1]);
 
    for(size_t i = l, j = 0, k = m - l + 1; i <= r; i++)
    {
        if(j > m - l)      buf[i] = tmp[k++];
        else if(k > r - l) buf[i] = tmp[j++];
        else               buf[i] = (tmp[j] < tmp[k]) ? tmp[j++] : tmp[k++];
    }
}

Существует также итеративный алгоритм сортировки, избавленный от рекурсивных вызовов. Такой алгоритм называют «Восходящей сортировкой слиянием».
// Слияние двух упорядоченных массивов
// m1 - Первый массив
// m2 - Второй массив
// l1 - Длина первого массива
// l2 - Длина второго массива
// Возвращает объединённый массив
               template <class T>
T* merge(T *m1, T* m2, int l1, int l2)
{
    T* ret = new T[l1+l2];
    int n = 0;
    // Сливаем массивы, пока один не закончится
    while (l1 && l2)
    {
        if (*m1 < *m2)
        {
            ret[n] = *m1;
            m1++;
            l1--;
        }
        else
        {
            ret[n] = *m2;
            m2++;
            l2--;
        }
        n++;
    }
    // Если закончился первый массив
    if (l1 == 0)
    {
        for (int i=0; i<l2; i++)
        {
            ret[n++] = *m2++;
        }
    }
    // Если закончился второй массив
    else
    {
        for (int i=0; i<l1; i++)
        {
            ret[n++] = *m1++;
        }
    }
    return ret;
}
 
// Функция восходящего слияния
template <class T>
void mergeSort(T * mas, int len)
{
    int n = 1, l, ost;
    T * mas1;
    while (n < len)
    {
        l = 0;
        while (l < len)
        {
            if (l+n >= len) break;
            ost = (l+n*2>len) ? (len-(l+n)) : n;
            mas1 = merge(mas + l, mas + l + n, n, ost);
            for (int i = 0; i<n+ost; i++) mas[l+i] = mas1[i];
            delete [] mas1;
            l += n*2;
        }
        n *= 2;
    }
}

Пример: char a[] = "ASORTINGEXAMPLE"; mergeSort(a, 16); Альтернативная версия алгоритма Сортировки Слиянием.

               template <typename Item>
void Merge(Item Mas[], int left, int right, int medium)
{
    int j = left;
    int k = medium + 1;
    int count = right - left + 1;
 
    if (count <= 1) return;
 
    Item *TmpMas = new Item[count];
 
    for (int i = 0; i < count; i++)
    {
        if (j <= medium && k <= right)
        {
            if (Mas[j] < Mas[k])
                TmpMas[i] = Mas[j++];
            else
                TmpMas[i] = Mas[k++];
        }
        else
        {
            if (j <= medium)
                TmpMas[i] = Mas[j++];
            else
                TmpMas[i] = Mas[k++];
        }
    }
 
    j = 0;
    for (int i = left; i <= right; i++)
    {
        Mas[i] = TmpMas[j++];
    }
    delete[] TmpMas;
}
 
template <typename Item>
void MergeSort(Item a[], int l, int r)
{
    int m;
 
    // Условие выхода из рекурсии
    if(l >= r) return;
 
    m = (l + r) / 2;
 
    // Рекурсивная сортировка полученных массивов
    MergeSort(a, l, m);
    MergeSort(a, m + 1, r);
    Merge(a, l, r, m);
}

C#
        static Int32[] Merge_Sort(Int32[] massive)
        {
            if (massive.Length == 1)
                return massive;
            Int32 mid_point = massive.Length / 2;
            return Merge(Merge_Sort(massive.Take(mid_point).ToArray()), Merge_Sort(massive.Skip(mid_point).ToArray()));
        }
 
        static Int32[] Merge(Int32[] mass1, Int32[] mass2)
        {
            Int32 a = 0, b = 0;
            Int32[] merged = new int[mass1.Length + mass2.Length];
            for (Int32 i = 0; i < mass1.Length + mass2.Length; i++)
            {
                if (b < mass2.Length && a < mass1.Length)
                    if (mass1[a] > mass2[b] && b < mass2.Length)
                        merged[i] = mass2[b++];
                    else //if int go for
                        merged[i] = mass1[a++];
                else
                    if (b < mass2.Length)
                        merged[i] = mass2[b++];
                    else
                        merged[i] = mass1[a++];
            }
            return merged;
        }
 
    static void Main(string[] args)
        {
              Int32[] arr = new Int32[100];
              //заполняем массив случайными числами
              Random rd = new Random();
              for(Int32 i = 0; i < arr.Length; ++i) {
                 arr[i] = rd.Next(1, 101);
              }
              System.Console.WriteLine("The array before sorting:");
              foreach (Int32 x in arr)
              {
                 System.Console.Write(x + " ");
              }
              //сортировка
 
              arr = Merge_Sort(arr);
 
              System.Console.WriteLine("\n\nThe array after sorting:");
              foreach (Int32 x in arr)
              {
                 System.Console.Write(x + " ");
              }
              System.Console.WriteLine("\n\nPress the <Enter> key");
              System.Console.ReadLine();
        }

Perl

@out=(5,2,8,9,4,2,7,9,4,1,6,9,0);
sub sortM{
    my($array,$first,$last)=@_;
    if($last>$first){
        my$middle=int(($last+$first)/2);
        sortM($array,$first,$middle);
        sortM($array,$middle+1,$last);
        my$j=0;
        $work[$j++]=$$array[$_]for($first..$last);
        $middle=int(($first+$last)/2)if($middle>$last);
        my$n=$middle-$first+1;
        for($i=$first,$j=0,$k=$n;$i<=$last;$i++){
            if(($j<$n)&&(($k==(($last-$first)+1))||($work[$j]lt$work[$k]))){
                $$array[$i]=$work[$j++]
            }else{
                $$array[$i]=$work[$k++];
            }
        }
    }
}
sortM(\@out,0,$#out+1);

Паскаль (сортировка текстовых файлов)
Сортировка простым слиянием
Procedure MergeSort(name: string; var f: text);
          Var a1,a2,s,i,j,kol,tmp: integer;
              f1,f2: text;
              b: boolean;
          Begin
             kol:=0;
 
             Assign(f,name);
             Reset(f);
             While not EOF(f) do
               begin
                 read(f,a1);
                 inc(kol);
               End;
             Close(f);
 
             Assign(f1,'{имя 1-го вспомогательного файла}');
             Assign(f2,'{имя 2-го вспомогательного файла}');
 
             s:=1;
             While (s<kol) do
               begin
 
                 Reset(f); Rewrite(f1); Rewrite(f2);
                 For i:=1 to kol div 2 do
                   begin
                     Read(f,a1);
                     Write(f1,a1,' ');
                   End;
                 If (kol div 2) mod s<>0 then
                   begin
                     tmp:=kol div 2;
                     While tmp mod s<>0 do
                       begin
                         Read(f,a1);
                         Write(f1,a1,' ');
                         inc(tmp);
                       End;
                   End;
                 While not EOF(f) do
                   begin
                     Read(f,a2);
                     Write(f2,a2,' ');
                   End;
                 Close(f); Close(f1); Close(f2);
 
 
                 Rewrite(f); Reset(f1); Reset(f2);
                 Read(f1,a1); 
                 Read(f2,a2);
                 While (not EOF(f1)) and (not EOF(f2)) do
                   begin
                     i:=0; j:=0;
                     b:=true;
                     While (b) and (not EOF(f1)) and (not EOF(f2)) do
                       begin
                         If (a1<a2) then
                           begin
                             Write(f,a1,' ');
                             Read(f1,a1);
                             inc(i);
                           End
                         else
                           begin
                             Write(f,a2,' ');
                             Read(f2,a2);
                             inc(j);
                           End;
                         If (i=s) or (j=s) then b:=false;
                       End;
                     If not b then
                       begin
                         While (i<s) and (not EOF(f1)) do
                           begin
                             Write(f,a1,' ');
                             Read(f1,a1);
                             inc(i);
                           End;
                         While (j<s) and (not EOF(f2)) do
                           begin
                             Write(f,a2,' ');
                             Read(f2,a2);
                             inc(j);
                           End;
                       End;
                   End;
                 While not EOF(f1) do
                   begin
                     tmp:=a1;
                     Read(f1,a1);
                     If not EOF(f1) then
                       Write(f,tmp,' ')
                     else
                       Write(f,tmp);
                   End;
                 While not EOF(f2) do
                   begin
                     tmp:=a2;
                     Read(f2,a2);
                     If not EOF(f2) then
                       Write(f,tmp,' ')
                     else
                       Write(f,tmp);
                   End;
                 Close(f); Close(f1); Close(f2);
 
                 s:=s*2;
               End;
             Erase(f1);
             Erase(f2);
          End;

Сортировка естественным слиянием
Procedure MergeSort(name: string; var f: text);
          Var s1,s2,a1,a2,where,tmp: integer;
              f1,f2: text;
          Begin
             s1:=5; s2:=5; {Можно задать любые числа, которые запустят цикл while}
             Assign(f,name);
             Assign(f1,'{имя 1-го вспомогательного файла}');
             Assign(f2,'{имя 2-го вспомогательного файла}');
             While (s1>1) and (s2>=1) do
               begin
                 where:=1;
                 s1:=0; s2:=0;
                 Reset(f); Rewrite(f1); Rewrite(f2);
                 Read(f,a1);
                 Write(f1,a1,' ');
                 While not EOF(f) do
                   begin
                     read(f,a2);
                     If (a2<a1) then
                       begin
                         Case where of
                            1: begin
                                 where:=2;
                                 inc(s1);
                               End;
                            2: begin
                                 where:=1;
                                 inc(s2);
                               End;
                         End;
                       End;
                     Case where of
                        1: write(f1,a2,' ');
                        2: write(f2,a2,' ');
                     End;
                     a1:=a2;
                   End;
                 If where=2 then
                   inc(s2)
                 else
                   inc(s1);
                 Close(f); Close(f1); Close(f2);
 
 
                 Rewrite(f); Reset(f1); Reset(f2);
                 Read(f1,a1);
                 Read(f2,a2);
                 While (not EOF(f1)) and (not EOF(f2)) do
                   begin
                     If (a1<=a2) then
                       begin
                         Write(f,a1,' ');
                         Read(f1,a1);
                       End
                     else
                       begin
                         Write(f,a2,' ');
                         Read(f2,a2);
                       End;
                   End;
                 While not EOF(f1) do
                   begin
                     tmp:=a1;
                     Read(f1,a1);
                     If not EOF(f1) then
                        Write(f,tmp,' ')
                     else
                        Write(f,tmp);
                   End;
                 While not EOF(f2) do
                   begin
                     tmp:=a2;
                     Read(f2,a2);
                     If not EOF(f2) then
                        Write(f,tmp,' ')
                     else
                        Write(f,tmp);
                   End;
                 Close(f); Close(f1); Close(f2);
               End; 
             Erase(f1);
             Erase(f2);
          End;

Delphi (сортировка произвольных типов данных - простое слияние)
unit uMergeSort;
 
interface
type
  TItem = Integer;               //Здесь можно написать Ваш произвольный тип
  TArray = array of TItem;
 
  procedure MergeSort(var Arr: TArray);
 
implementation
 
function IsBigger(d1, d2 : TItem) : Boolean;
begin
  Result := (d1 > d2);     //Сравниваем d1 и d2. Не обязательно так. Зависит от Вашего типа.
  //Сюда можно добавить счетчик сравнений
end;
 
//Процедура сортировки слияниями
procedure MergeSort(var Arr: TArray);
var
  tmp : TArray; //Временный буфер // А где реализация процедуры? Этот код работать не будет, допишите, пожалуйста
  //Слияние
  procedure merge(L, Spl, R : Integer);
  var
    i, j, k : Integer;
  begin
    i := L;
    j := Spl + 1;
    k := 0;
    //Выбираем меньший из первых и добавляем в tmp
    while (i <= Spl) and (j <=R) do
    begin
      if IsBigger(Arr[i], Arr[j]) then
      begin
        tmp[k] := Arr[j];
        Inc(j);
      end
      else
      begin
        tmp[k] := Arr[i];
        Inc(i);
      end;
      Inc(k);
    end;
    //Просто дописываем в tmp оставшиеся эл-ты
    if i <= Spl then      //Если первая часть не пуста
      for j := i to Spl do
      begin
        tmp[k] := Arr[j];
        Inc(k);
      end
    else                  //Если вторая часть не пуста
      for i := j to R do
      begin
        tmp[k] := Arr[i];
        Inc(k);
      end;
    //Перемещаем из tmp в arr
    Move(tmp[0], Arr[L], k*SizeOf(TItem));
  end;
 
  //Сортировка
  procedure sort(L, R : Integer);
  var
    splitter : Integer;
  begin
    //Массив из 1-го эл-та упорядочен по определению
    if L >= R then Exit;
    splitter := (L + R) div 2;  //Делим массив пополам
    sort(L, splitter);          //Сортируем каждую
    sort(splitter + 1, R);      //часть по отдельности
    merge(L, splitter, R);      //Производим слияние
  end;
 
  //Основная часть процедуры сортировки
begin
  SetLength(tmp, Length(Arr));
  sort(0, Length(Arr) - 1);
  SetLength(tmp, 0);
end;
 
end.

D
void mergeSort(int[] array) {
    static void merge(int[] array, int q) {
        int[] leftArray = array[0..q].dup ~ int.max;
        int[] rightArray = array[q..$].dup ~ int.max;
        int i = 0;
        int j = 0;
        int length = array.length;
        for (int k = 0; k < length; ++k) {
            array[k] = (leftArray[i] <= rightArray[j]) ? leftArray[i++] : rightArray[j++];
        }
    }
 
    if (array.length > 1) {
        int q = array.length / 2;
        mergeSort(array[0..q]);
        mergeSort(array[q..$]);
        merge(array, q);
    }
}

Добавлено: 14 Апреля 2018 06:51:55 Добавил: Андрей Ковальчук

Шалости с элементом canvas: скользящие ленты

Шалости с элементом canvas: скользящие ленты
В данном уроке мы продемонстрируем возможности работы с элементом canvas. В итоге получится визуальный эффект с разноцветными скользящими лентами. Никакого Flash - сплошной JavaScript.

Разметка для шалости очень проста:

<canvas id="canvas"></canvas>

Также будем использовать немного CSS:
#canvas {
    display: block;
    /*Заполняем элемент canvas черным цветом по умолчанию*/
    background: #000;
}

Все остальное реализовано в JavaScript:
window.onload = function(){
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
     
    //Элемент canvas занимает все доступное пространство
    var W = window.innerWidth, H = window.innerHeight;
    canvas.width = W;
    canvas.height = H;
     
    //Создаем новые частицы
    var particles = [];
    for(var i = 0; i < 25; i++)
    {
        particles.push(new particle());
    }
     
    function particle()
    {
        //Расположение в элементе canvas
        this.location = {x: Math.random()*W, y: Math.random()*H};
        //Радиус - устанавливаем равным 0
        this.radius = 0;
        //Скорость
        this.speed = 3;
        //Угол направления в градусах от 0 до 360
        this.angle = Math.random()*360;
        //Цвета
        var r = Math.round(Math.random()*255);
        var g = Math.round(Math.random()*255);
        var b = Math.round(Math.random()*255);
        var a = Math.random();
        this.rgba = "rgba("+r+", "+g+", "+b+", "+a+")";
    }
     
    //Выводим частицы
    function draw()
    {
        //Перекрашиваем фон
        //Заполним canvas черным
        //Уменьшаем непрозрачность фона
        ctx.globalCompositeOperation = "source-over";
        ctx.fillStyle = "rgba(0, 0, 0, 0.02)";
        ctx.fillRect(0, 0, W, H);
        ctx.globalCompositeOperation = "lighter";
         
        for(var i = 0; i < particles.length; i++)
        {
            var p = particles[i];
            ctx.fillStyle = "white";
            ctx.fillRect(p.location.x, p.location.y, p.radius, p.radius);
             
            //Сдвигаем частицы
            //Создаем набор частиц сдвинутых в произвольном направлении
            //с такой же скоростью
            for(var n = 0; n < particles.length; n++)
            {
                var p2 = particles[n];
                //Вычисляем дистанциюпо отнешению к другим частицам
                var yd = p2.location.y - p.location.y;
                var xd = p2.location.x - p.location.x;
                var distance = Math.sqrt(xd*xd + yd*yd);
                //Выводим линию между обеими частицами, если дистанция между ними в диапазоне 200px
                if(distance < 200)
                {
                    ctx.beginPath();
                    ctx.lineWidth = 1;
                    ctx.moveTo(p.location.x, p.location.y);
                    ctx.lineTo(p2.location.x, p2.location.y);
                    ctx.strokeStyle = p.rgba;
                    ctx.stroke();
                    //Теперь появлется лента
                }
            }
             
            //Используем похожий вектор
            //Новый x = старый x + скорость * cos(угол)
            p.location.x = p.location.x + p.speed*Math.cos(p.angle*Math.PI/180);
            //Новый y = старый y + скорость * sin(угол)
            p.location.y = p.location.y + p.speed*Math.sin(p.angle*Math.PI/180);
             
            if(p.location.x < 0) p.location.x = W;
            if(p.location.x > W) p.location.x = 0;
            if(p.location.y < 0) p.location.y = H;
            if(p.location.y > H) p.location.y = 0;
        }
    }
     
    setInterval(draw, 30);
}

Готово!

Добавлено: 14 Апреля 2018 06:37:43 Добавил: Андрей Ковальчук

Примеры реализации пирамидальной сортировки

Примеры реализации пирамидальной сортировки

C

#include <stdio.h>
 
#define MAXL 1000
 
void swap (int *a, int *b)
{
  int t = *a;
  *a = *b;
  *b = t;
}
int main()
{
  int a[MAXL], n, i, sh = 0, b = 0;
  scanf ("%i", &n);
  for (i = 0; i < n; ++i)
    scanf ("%i", &a[i]);
  while (1)
  {
    b = 0;
    for (i = 0; i < n; ++i)
    {
      if (i*2 + 2 + sh < n)
      {
        if (a[i+sh] > a[i*2 + 1 + sh] || a[i + sh] > a[i*2 + 2 + sh])
        {
          if (a[i*2+1+sh] < a[i*2+2+sh])
          {
            swap (&a[i+sh], &a[i*2+1+sh]);
            b = 1;
          }
          else if (a[i*2+2+sh] < a[i*2+1+sh])
          {
            swap (&a[i+sh],&a[i*2+2+sh]);
            b = 1;
          }
        }
      }
      else if (i * 2 + 1 + sh < n)
      {
        if (a[i+sh] > a[i*2+1+sh])
        {
          swap (&a[i+sh], &a[i*2+1+sh]);
          b=1;
        }
      }
    }
    if (!b) sh++;
    if (sh+2==n)
      break;
  }
  for (i = 0; i < n; ++i)
    printf ("%i%c", a[i], (i!=n-1)?' ':'\n');
  return 0;
}

C++
#include <iterator>
 
template< typename Iterator >
void adjust_heap( Iterator first
                  , typename std::iterator_traits< Iterator >::difference_type current
                  , typename std::iterator_traits< Iterator >::difference_type size
                  , typename std::iterator_traits< Iterator >::value_type tmp )
{
    typedef typename std::iterator_traits< Iterator >::difference_type diff_t;
 
    diff_t top = current, next = 2 * current + 2;
 
    for ( ; next < size; current = next, next = 2 * next + 2 )
    {
        if ( *(first + next) < *(first + next - 1) )
            --next;
        *(first + current) = *(first + next);
    }
 
    if ( next == size )
        *(first + current) = *(first + size - 1), current = size - 1;
 
    for ( next = (current - 1) / 2;
          top > current && *(first + next) < tmp;
          current = next, next = (current - 1) / 2 )
    {
        *(first + current) = *(first + next);
    }
    *(first + current) = tmp;
}
 
template< typename Iterator >
void pop_heap( Iterator first, Iterator last)
{
    typedef typename std::iterator_traits< Iterator >::value_type value_t;
 
    value_t tmp = *--last;
    *last = *first;
    adjust_heap( first, 0, last - first, tmp );
}
 
template< typename Iterator >
void heap_sort( Iterator first, Iterator last )
{
    typedef typename std::iterator_traits< Iterator >::difference_type diff_t;
    for ( diff_t current = (last - first) / 2 - 1; current >= 0; --current )
        adjust_heap( first, current, last - first, *(first + current) );
 
    while ( first < last )
        pop_heap( first, last-- );
}

C++ (другой вариант)
#include <iostream>
#include <conio.h>
 
using namespace std;
 
void iswap(int &n1, int &n2)
{
    int temp = n1;
    n1 = n2;
    n2 = temp;
}
 
int main()
{
    int const n = 100;
    int a[n];
    for ( int i = 0; i < n; ++i ) { a[i] = n - i; cout << a[i] << " "; }
        //заполняем массив для наглядности.
        //-----------сортировка------------// 
        //сортирует по-возрастанию. чтобы настроить по-убыванию, 
        //поменяйте знаки сравнения в строчках, помеченных /*(знак)*/
    int sh = 0; //смещение
    bool b = false;
    for(;;)
    {
        b = false;
        for ( int i = 0; i < n; i++ )
        {
            if( i * 2 + 2 + sh < n )
            {
                if( ( a[i + sh] > /*<*/ a[i * 2 + 1 + sh] ) || ( a[i + sh] > /*<*/ a[i * 2 + 2 + sh] ) )
                {
                    if ( a[i * 2 + 1 + sh] < /*>*/ a[i * 2 + 2 + sh] ) 
                    {
                        iswap( a[i + sh], a[i * 2 + 1 + sh] );
                        b = true;
                    }
                    else if ( a[i * 2 + 2 + sh] < /*>*/ a[ i * 2 + 1 + sh]) 
                         {
                             iswap( a[ i + sh], a[i * 2 + 2 + sh]);
                             b = true;
                         }
                }
                //дополнительная проверка для последних двух элементов
               //с помощью этой проверки можно отсортировать пирамиду 
               //состоящую всего лишь из трех жлементов
                    if( a[i*2 + 2 + sh] < /*>*/ a[i*2 + 1 + sh] ) 
                        {
                        iswap( a[i*2+1+sh], a[i * 2 +2+ sh] );
                        b = true;
                        }
            }
            else if( i * 2 + 1 + sh < n )
                 {
                     if( a[i + sh] > /*<*/ a[ i * 2 + 1 + sh] )
                     {
                         iswap( a[i + sh], a[i * 2 + 1 + sh] );
                         b = true;
                     }
                 }
        }
        if (!b) sh++; //смещение увеличивается, когда на текущем этапе 
                      //сортировать больше нечего
        if ( sh + 2 == n ) break; 
    }  //конец сортировки
 
 
    cout << endl << endl;
    for ( int i = 0; i < n; ++i ) cout << a[i] << " "; 
 
 
    _getch();
    return 0;
}

C#
       static Int32 add2pyramid(Int32[] arr, Int32 i, Int32 N)
        {
            Int32 imax;
            Int32 buf;
            if ((2 * i + 2) < N)
            {
                if (arr[2 * i + 1] < arr[2 * i + 2]) imax = 2 * i + 2;
                else imax = 2 * i + 1;
            }
            else imax = 2 * i + 1;
            if (imax >= N) return i;
            if (arr[i] < arr[imax])
            {
                buf = arr[i];
                arr[i] = arr[imax];
                arr[imax] = buf;
                if (imax < N / 2) i = imax;
            }
            return i;
        }
 
        static void Pyramid_Sort(Int32[] arr, Int32 len)
        {
            //step 1: building the pyramid
            for (Int32 i = len / 2 - 1; i >= 0; --i)
            {
                long prev_i = i;
                i = add2pyramid(arr, i, len);
                if (prev_i != i) ++i;
            }
 
            //step 2: sorting
            Int32 buf;
            for (Int32 k = len - 1; k > 0; --k)
            {
                buf = arr[0];
                arr[0] = arr[k];
                arr[k] = buf;
                Int32 i = 0, prev_i = -1;
                while (i != prev_i)
                {
                    prev_i = i;
                    i = add2pyramid(arr, i, k);
                }
            }
        }
 
        static void Main(string[] args)
        {
              Int32[] arr = new Int32[100];
              //заполняем массив случайными числами
              Random rd = new Random();
              for(Int32 i = 0; i < arr.Length; ++i) {
                 arr[i] = rd.Next(1, 101);
              }
              System.Console.WriteLine("The array before sorting:");
              foreach (Int32 x in arr)
              {
                 System.Console.Write(x + " ");
              }
              //сортировка
              Pyramid_Sort(arr, arr.Length);
 
              System.Console.WriteLine("\n\nThe array after sorting:");
              foreach (Int32 x in arr)
              {
                 System.Console.Write(x + " ");
              }
              System.Console.WriteLine("\n\nPress the <Enter> key");
              System.Console.ReadLine();
        }

C# (другой вариант)
public class Heap<T> 
{
        private T[] _array; //массив сортируемых элементов
        private int heapsize;//число необработанных элементов 
        private IComparer<T> _comparer;
        public Heap(T[] a, IComparer<T> comparer){ 
                _array = a; 
                heapsize = a.Length; 
                _comparer = comparer; 
        }
 
        public void HeapSort(){
                build_max_heap();//Построение пирамиды
                for(int i = _array.Length - 1; i > 0; i--){
 
                        T temp = _array[0];//Переместим текущий максимальный элемент из нулевой позиции в хвост массива
                        _array[0] = _array[i];
                        _array[i] = temp;
 
                        heapsize--;//Уменьшим число необработанных элементов
                        max_heapify(0);//Восстановление свойства пирамиды
                }
        }
 
        private int parent (int i) { return (i-1)/2; }//Индекс родительского узла
        private int left (int i) { return 2*i+1; }//Индекс левого потомка
        private int right (int i) { return 2*i+2; }//Индекс правого потомка
 
        //Метод переупорядочивает элементы пирамиды при условии, 
        //что элемент с индексом i меньше хотя бы одного из своих потомков, нарушая тем самым свойство невозрастающей пирамиды
        private void max_heapify(int i){
                int l = left(i);
                int r = right(i);
                int lagest = i;
                if (l<heapsize && _comparer.Compare(_array[l], _array[i])>0)
                        lagest = l;                                             
                if (r<heapsize && _comparer.Compare(_array[r], _array[lagest])>0)
                        lagest = r;
                if (lagest != i)
                {
                        T temp = _array[i];
                        _array[i] = _array[lagest];
                        _array[lagest] = temp;
 
                        max_heapify(lagest);
                }
        }
 
        //метод строит невозрастающую пирамиду 
        private void build_max_heap(){
                int i = (_array.Length-1)/2;
 
                while(i>=0){
                        max_heapify(i);         
                        i--;
                }
        }       
 
}
 
public class IntComparer : IComparer<int>
{
        public int Compare(int x, int y) {return x-y;}
}
 
public static void Main (string[] args)
{
        int[] arr = Console.ReadLine().Split(' ').Select(s=>int.Parse(s)).ToArray();//вводим элементы массива через пробел
        IntComparer myComparer = new IntComparer();//Класс, реализующий сравнение
        Heap<int> heap = new Heap<int>(arr, myComparer);
        heap.HeapSort();        
}

Здесь T - любой тип, на множестве элементов которого можно ввести отношение частичного порядка.

Pascal
Вместо «SomeType» следует подставить любой из арифметических типов (например integer).

procedure Sort(var Arr: array of SomeType; Count: Integer);
 
  procedure DownHeap(index, Count: integer; Current: SomeType);
  //Функция пробегает по пирамиде восстанавливая ее
  //Также используется для изначального создания пирамиды
  //Использование: Передать номер следующего элемента в index
  //Процедура пробежит по всем потомкам и найдет нужное место для следующего элемента
  var
    Child: Integer;
  begin
    while index < Count div 2 do begin
      Child := (index+1)*2-1;
      if (Child < Count-1) and (Arr[Child] < Arr[Child+1]) then
        Child:=Child+1;
      if Current >= Arr[Child] then
        break;
      Arr[index] := Arr[Child];
      index := Child;
    end;
    Arr[index] := Current;
  end;
 
//Основная функция
var
  i: integer;
  Current: SomeType;
begin
  //Собираем пирамиду
  for i := (Count div 2)-1 downto 0 do
    DownHeap(i, Count, Arr[i]);
  //Пирамида собрана. Теперь сортируем
  for i := Count-1 downto 0 do begin
    Current := Arr[i]; //перемещаем верхушку в начало отсортированного списка
    Arr[i] := Arr[0];
    DownHeap(0, i, Current); //находим нужное место в пирамиде для нового элемента
  end;
end;

Pascal (другой вариант)
Примечание: myarray = array[1..Size] of integer; N — количество элементов массива

procedure HeapSort(var m: myarray; N: integer);
var
  i: integer;
 
  procedure Swap(var a,b:integer);
  var
    tmp: integer;
  begin
    tmp:=a;
    a:=b;
    b:=tmp;
  end;
 
  procedure Sort(Ns: integer);
  var
    i, tmp, pos, mid: integer;
  begin
    mid := Ns div 2;
    for i := mid downto 1 do
    begin
      pos := i;
      while pos<=mid do
      begin
        tmp := pos*2;
        if tmp<Ns then
        begin
          if m[tmp+1]<m[tmp] then
            tmp := tmp+1;
          if m[pos]>m[tmp] then
          begin
            Swap(m[pos], m[tmp]);
            pos := tmp;
          end
          else
            pos := Ns;
        end
        else
          if m[pos]>m[tmp] then
          begin
            Swap(m[pos], m[tmp]);
            pos := Ns;
          end
          else
            pos := Ns;
        end;
      end;
    end;
begin
  for i:=N downto 2 do
  begin
    Sort(i);
    Swap(m[1], m[i]);
  end;
end;

Pascal (третий вариант)
//процедура для перессылки записей
procedure swap(var x,y:integer);
var temp:integer;
begin
  temp:=x;
  x:=y;
  y:=temp;
end;
 
//процедура приведения массива к пирамидальному виду (to pyramide)
procedure toPyr(var data:TArray; n:integer); //n - размерность массива
var i:integer;
begin
  for i:=n div 2 downto 1 do begin
    if 2*i<=n then if data[i]<data[2*i] then swap(data[i],data[2*i]);
    if 2*i+1<=n then if data[i]<data[2*i+1] then swap(data[i],data[2*i+1]);
  end;
end;
 
//процедура для сдвига массива влево
procedure left(var data:TArray; n:integer);
var i:integer;
    temp:integer;
begin
  temp:=data[1];
  for i:=1 to n-1 do
    data[i]:=data[i+1];
  data[n]:=temp;
end;
 
//основная программа
begin
  for i:=n downto 1 do begin
    topyr(a,i);
    left(a,n);
end;

Python
def heapSort(li):
    """Сортирует список в возрастающем порядке с помощью алгоритма пирамидальной сортировки"""
 
    def downHeap(li, k, n):
        new_elem = li[k]
        while 2*k+1 < n:
            child = 2*k+1
            if child+1 < n and li[child] < li[child+1]:
                child += 1
            if new_elem >= li[child]:
                break
            li[k] = li[child]
            k = child
        li[k] = new_elem
 
    size = len(li)
    for i in range(size//2-1,-1,-1):
        downHeap(li, i, size)
    for i in range(size-1,0,-1):
        temp = li[i]
        li[i] = li[0]
        li[0] = temp
        downHeap(li, 0, i)

Python (другой вариант)
def heapsort(s):                                 
    sl = len(s)                                    
 
    def swap(pi, ci):                              
        if s[pi] < s[ci]:                          
            s[pi], s[ci] = s[ci], s[pi]            
 
    def sift(pi, unsorted):                        
        i_gt = lambda a, b: a if s[a] > s[b] else b
        while pi*2+2 < unsorted:                   
            gtci = i_gt(pi*2+1, pi*2+2)            
            swap(pi, gtci)                         
            pi = gtci                              
    # heapify                                      
    for i in range((sl/2)-1, -1, -1):              
        sift(i, sl)                                
    # sort                                         
    for i in range(sl-1, 0, -1):                   
        swap(i, 0)                                 
        sift(0, i)

Perl
@out=(6,4,2,8,5,3,1,6,8,4,3,2,7,9,1)
$N=@out+0;
if($N>1){
    while($sh+2!=$N){
        $b=undef;
        for my$i(0..$N-1){
            if($i*2+2+$sh<$N){
                if($out[$i+$sh]gt$out[$i*2+1+$sh] || $out[$i+$sh]gt$out[$i*2+2+$sh]){
                    if($out[$i*2+1+$sh]lt$out[$i*2+2+$sh]){
                        ($out[$i*2+1+$sh],$out[$i+$sh])=($out[$i+$sh],$out[$i*2+1+$sh]);
                        $b=1;
                    }elsif($out[$i*2+2+$sh]lt$out[$i*2+1+$sh]){
                        ($out[$i*2+2+$sh],$out[$i+$sh])=($out[$i+$sh],$out[$i*2+2+$sh]);
                        $b=1;
                    }
                }elsif($out[$i*2+2+$sh]lt$out[$i*2+1+$sh]){
                    ($out[$i*2+1+$sh],$out[$i*2+2+$sh])=($out[$i*2+2+$sh],$out[$i*2+1+$sh]);
                    $b=1;
                }
            }elsif($i*2+1+$sh<$N && $out[$i+$sh]gt$out[$i*2+1+$sh]){
                ($out[$i+$sh],$out[$i*2+1+$sh])=($out[$i*2+1+$sh],$out[$i+$sh]);
                $b=1;
            }
        }
        ++$sh if!$b;
        last if$sh+2==$N;
    }
}

Добавлено: 13 Апреля 2018 19:14:34 Добавил: Андрей Ковальчук