
- •Квадратичные и субквадратичные алгоритмы
- •Логарифмические и линейные алгоритмы
- •Сравнение времени сортировок
- •Void selectSort(t a[], long size) {
- •Сортировка пузырьком
- •Void bubbleSort(t a[], long size) {
- •Void shakerSort(t a[], long size) {
- •Void insertSort(t a[], long size) {
- •Inline void insertSortGuarded(t a[], long size) {
- •Int increment(long inc[], long size) {
- •Void shellSort(t a[], long size) {
- •44 55 12 42 94 18 06 67 Исходный массив
- •Void downHeap(t a[], long k, long n) {
- •44 55 12 42 // 94 18 06 67 Справа - часть массива,
- •44 55 12 // 67 94 18 06 42 Свойству пирамиды,
- •44 // 94 18 67 55 12 06 42 Остальные элементы
- •94 67 18 44 55 12 06 42 // Иллюстрация 2-й
- •67 55 44 06 42 18 12 // 94 Во внутреннем
- •Void heapSort(t a[], long size) {
- •Void quickSortR(t* a, long n) {
- •Модификации кода и метода
- •Поразрядная сортировка для массивов
- •Сортировка подсчетом
- •Поразрядная сортировка беззнаковых целых чисел
- •Void createCounters(t *data, long *counters, long n) {
- •Void radixPass (short Offset, long n, t *source, t *dest, long *count) {
- •Void radixSort (t* &in, long n) {
- •Поразрядная сортировка целых чисел со знаком
- •Void signedRadixLastPass (short Offset, long n, t *source, t *dest, long *count) {
- •Void signedRadixSort (t* &in, long n) {
- •Формат ieee-754
- •Поразрядная сортировка целых чисел с плавающей точкой
- •Void floatRadixLastPass (short Offset, long n, t *source, t *dest, long *count) {
- •Void floatRadixSort (t* &in, long n) {
- •Эффективность поразрядной сортировки
- •Результаты тестирования
Void signedRadixSort (t* &in, long n) {
T *out = new T[N];
ushort i;
long *counters = new long[sizeof(T)*256], *count;
createCounters(in, counters, N);
for (i=0; i<sizeof(T)-1; i++) {
count = counters + 256*i;
if ( count[0] == N ) continue;
radixPass (i, N, in, out, count);
swap(in, out);
}
count = counters + 256*i;
signedRadixLastPass (i, N, in, out, count);
delete in;
in = out;
delete counters;
}
Формат ieee-754
Особенно подходящим местом применения radixSort является компьютерная графика. Есть много координат, которые необходимо отсортировать, причем с наибольшей скоростью. Поэтому было бы очень удобно распространить возможности процедуры на числа с плавающей точкой.
С другой стороны, существует несколько стандартов для представления таких чисел. Наиболее известным следует признать IEEE-754, который используется в IBM PC, Macintosh, Dreamcast и ряде других систем. Зафиксировав формат представления числа, уже можно модифицировать соответствующим образом сортировку.
Любое число можно записать в системе с основанием BASE как M*BASEn, где |M|<BASE. Например, 47110 = 4.7110 * 102, 6.510 = 6.510*100, -0.003210 = -3.210 * 10-3. В двоичной системе можно дополнительно сделать первую цифру M равной 1: 101.012 = 1.01012*22, -0.000011 = -1.12*2-5
Такая запись называется нормализованной. M называется мантиссой, n - порядком числа. Стандарт IEEE-754 предполагает запись числа в виде [знак][порядок][мантисса]. Различным форматам соответствует свой размер каждого из полей. Для чисел одинарной точности(float) это 1 бит под знак, 8 под порядок и 23 на мантиссу. Числа двойной точности(double) имеют порядок из 11 бит, мантиссу из 52 бит. Некоторые процессоры(например, 0x86) поддерживают расширенную точность(long double).
тип/бит
[Знак]
[Порядок]
[Мантисса]
[Смещение]
float
1
8
23
127
double
1
11
52
1023
Рассмотрим числа одинарной точности(float). Как и в целых числах, значение знакового бита 0 означает, что число положительное, значение 1 - число отрицательное. Так как первая цифра мантиссы всегда равна 1, то хранится только ее дробная часть. То есть, если M=1.010112, то [Мантисса]= 010112. Если M=1.10112, то [Мантисса]=10112. Таким образом в 23 битах хранится мантисса до 24 бит длиной. Чтобы получить из поля [Мантисса] правильное значение M необходимо мысленно прибавить к его значению единицу с точкой.
Для удобства представления отрицательного порядка в соответствующем поле реально хранится порядок+смещение. Например, если n=0, то [Порядок]=127. Если n=-7, то [Порядок]=120. Таким образом, его значение всегда неотрицательно.
Таким образом, общая формула по получению обычной записи числа из формата IEEE-754:
N = (-1)[Знак] * 1.[Мантисса] * 2[Порядок]-127 (нормализованная запись, 1)
Для 10.2510 = 1010.012 = +1.01001 * 23 соответствующие значения будут [Знак]=0 (+) , [Порядок] = 130(=3+127), [Мантисса] = 010012.
При значениях [Порядок]=1...254 эта система позволяет представлять числа приблизительно от +-3,39*10-38 до +-3,39*10+38.
Особым образом обрабатываются [Порядок]=0 и [Порядок]=255.
Если [Порядок]=0, но мантисса отлична от нуля, то перед ее началом необходимо ставить вместо единицы ноль с точкой. Так что формула меняется на
N = (-1)[Знак] * 0.[Мантисса] * 2-126 (денормализованная запись, 2)
Это расширяет интервал представления чисел до +-1,18*10-38. ... +-3,39*10+38
[Порядок]=0 [Мантисса]=0 обозначают ноль. Возможно существование двух нулей: +0 и -0, которые отличаются битом знака, но при операциях ведут себя одинаково. В этом смысле можно интерпретировать ноль как особое денормализованное число со специальным порядком.
Значение [Порядок]=255(все единицы) зарезервировано для специальных целей, более подробно описанных в стандарте. Такое поле в зависимости от мантиссы обозначает одно из трех специальных "нечисел", которые обозначают как Inf, NaN, Ind, и может появиться в результате ошибок в вычислениях и при переполнении.
Числа двойной точности устроены полностью аналогичным образом, к порядку прибавляется не 127, а 1023. Увеличение длин соответствующих полей позволяет хранить числа от 10-323.3 до 10308.3, значение [Порядок]=2047(все единицы) зарезервировано под "нечисла".