Обсуждение участника:KirillKutirev — различия между версиями
(→Алгоритм Хаффмана за O(n) .) |
(→Алгоритм Хаффмана за O(n) .) |
||
Строка 13: | Строка 13: | ||
В первом варианте мы просто дописываем сумму в конец второго массива. Во втором варианте мы вычеркиваем первый элемент из второго массива и добавляем его сумму с первым элементом первого массива в конец второго. Ну и в третьем варианте, мы вычеркиваем два первых элемента второго массива и добавляем их сумму в конец этого массива.Если в первом массиве элементы закончились, а во втором осталось больше одного элемента, то они меняются ролями. | В первом варианте мы просто дописываем сумму в конец второго массива. Во втором варианте мы вычеркиваем первый элемент из второго массива и добавляем его сумму с первым элементом первого массива в конец второго. Ну и в третьем варианте, мы вычеркиваем два первых элемента второго массива и добавляем их сумму в конец этого массива.Если в первом массиве элементы закончились, а во втором осталось больше одного элемента, то они меняются ролями. | ||
− | + | На каждом шаге количество элементов уменьшается ровно на один, а минимум из 4-х элементов мы выбираем за константное время, следовательно, программа делает ровно <tex>n</tex> итераций. | |
==Реализация== | ==Реализация== |
Версия 12:27, 6 января 2014
Алгоритм Хаффмана за .
У нас есть массив частот (массив, в котором хранится число вхождений каждого символа в строку), отсортированный по возрастанию, нужно построить по нему код Хаффмана за цифровой сортировкой за , что не ухудшит асимптотику).
(если массив не отсортирован, то это можно сделать, например,Идея алгоритма заключается в том, чтобы создать такую очередь с приоритетами, из которой можно было бы доставать два минимума за , после чего в эту же очередь с приоритетами положить их сумму за . У нас уже есть массив с отсортированными частотами, теперь давайте заведем второй массив, в котором мы будем хранить суммы. Несложно заметить, что в этом массиве элементы тоже будут идти по неубыванию. Допустим, что на каком-то шаге сумма получилась меньше чем предыдущая, но это противоречит тому, что на каждом шаге мы выбираем два минимальных (т.е. на каждом последующем шаге мы выбираем два минимума из элементов больших, чем на предыдущем шаге). На каждой итерации мы будет выбирать два минимума из четырех элементов (первые 2 элемента первого массива и первые 2 элемента второго массива). Теперь рассмотрим одну итерацию подробнее.
У нас есть три варианта возможных пар минимумов :
- Оба элемента из первого массива.
- Первый элемент первого массива и первый элемент второго массива.
- Два первых элемента второго массива.
В первом варианте мы просто дописываем сумму в конец второго массива. Во втором варианте мы вычеркиваем первый элемент из второго массива и добавляем его сумму с первым элементом первого массива в конец второго. Ну и в третьем варианте, мы вычеркиваем два первых элемента второго массива и добавляем их сумму в конец этого массива.Если в первом массиве элементы закончились, а во втором осталось больше одного элемента, то они меняются ролями.
На каждом шаге количество элементов уменьшается ровно на один, а минимум из 4-х элементов мы выбираем за константное время, следовательно, программа делает ровно
итераций.Реализация
Поскольку мы не ограничены по памяти, очень удобно использовать вместо двух одномерных массивов один двумерный. Это избавит код от громоздких "if".
sum = int[logMAXN][MAXN+1] // массив, в котором считаем суммы, сначала заполнен "бесконечностями" s1, s2 // указатели на строки, которые выполняют функции первого и второго массивов в описании алгоритма h1, h2 // указатели на первый элемент первой строки и второй строки соответственно t1, t2 // указатели на ячейки массивов сразу после последнего элемента в этих массивах n // количество элементов chek // считает на сколько стало меньше элементов // ... чтение данных while chek < n while h1 < t1 // проходим по массиву, выполняющему роль первого; внутри этого цикла мы ищем минимумы и записываем суммы if h2 == t2 sum[s2][t2] = sum[s1][h1] + sum[s1][h1+1] if t1 - h1 == 1 sum[s2][t2] = sum[s2][t2] - sum[s1][h1+1] h1 = h1 + 2 t2++ else if sum[s1][h1] < sum[s2][h2] if sum[s1][h1+1] < sum[s2][h2] sum[s2][t2] = sum[s1][h1] + sum[s1][h1+1] h1 += 2 else sum[s2][t2] = sum[s1][h1] + sum[s2][h2] h1++ h2++ t2++ else if sum[s1][h1] < sum[s2][h2+1] sum[s2][t2] = sum[s2][h2] + sum[s1][h1] h1++ h2++ else sum[s2][t2] = sum[s2][h2] + sum[s2][h2+1] h2+=2 t2++ chek++ // учитываем то, что элементов стало на 1 меньше s1 = s2 // строки меняются ролями, соответственно все их параметры тоже h1 = h2 t1 = t2 s2++ h2 = t2 = 0