Кто-нибудь на самом деле эффективно реализовал Фибоначчи-кучу?

N-мерные массивы произвольного типа и размера в C ++:

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

Я написал класс шаблона c ++ для создания n-мерного массива произвольного типа и размера. Он должен быть создан с типом массива и количеством измерений. Размер можно изменять динамически. Ниже приведена голая (лишенная) рабочая версия того, как создать многомерный массив, к которому можно получить доступ к элементам через последовательное применение оператора [] (например, массив [x] [y] [г]). Эта версия может обрабатывать только массивы размерности n> 1. Основная функция показывает, как создать в качестве примера 4-мерный массив целых чисел.

EDIT: имейте в виду, что приведенный ниже пример минимальный для удобочитаемости, поскольку он делает не освобождать массив, а также не проверяет границы доступа. Добавление этого тривиально и осталось программисту.

#include <stdio.h>
#include <stdlib.h>

template <typename T, int N>
struct array {
    array<T,N>() : data(NULL), offset((int*) malloc(sizeof(int)*N)){}
    array<T,N>(T *data, int *offset) : data(data), offset(offset){}
    array<T,N-1> operator[](int i){return array<T,N-1>(&data[i*offset[N]], offset);}
    bool resize(int *size){
        offset[N-1] = 1;
        int total_size = size[N-1];
        for(int i = N-2; i >= 0; i--){
            total_size *= size[i];
            offset[i] = offset[i+1]*size[i+1];
        }
        return (data = (T*) realloc (data, total_size*sizeof(T)));
    }
    T *data;
    int *offset;
};

template <typename T>
struct array<T,1>{
    array<T,1>(T *data, int *offset) : data(data){}
    T& operator[](int i){return data[i];}
    T *data;
};

int main () {
    array<int, 4> a;

    // create array with dimensions [1][3][3][7]
    int size[4] = { 1, 3, 3, 7 };
    a.resize(size);               

    a[0][1][2][3] = 123;

    return 0;
}

Наслаждайтесь.

147
задан templatetypedef 31 January 2012 в 21:33
поделиться

2 ответа

<забастовка> Повышение библиотеки C++ включает реализацию "кучи" Fibonacci в boost/pending/fibonacci_heap.hpp. Этот файл, по-видимому, был в pending/ в течение многих лет, и моими проекциями никогда не будет приниматься. Кроме того, в той реализации были ошибки, которые были исправлены моим знакомством и всесторонним спокойным парнем Aaron Windsor. К сожалению, большинство версий того файла, который я мог найти онлайн (и тот в libboost-dev пакете Ubuntu) все еще, имело ошибки; я должен был вытянуть чистая версия из репозитория Подверсии.

Начиная с Повышения версии 1.49 библиотеки C++ добавили много новых структур "кучи" включая fibonacci "кучу".

я смог скомпилировать dijkstra_ heap_ performance.cpp против измененной версии [1 111] dijkstra_ shortest_ paths.hpp для сравнения "кучи" Fibonacci и двоичной "кучи". (В строке typedef relaxed_heap<Vertex, IndirectCmp, IndexMap> MutableQueue, изменение relaxed к fibonacci.) Я сначала забыл компилировать с оптимизацией, в этом случае Fibonacci и двоичная "куча" выполняют о том же с "кучей" Fibonacci, обычно превосходящей по характеристикам незначительной суммой. После того, как я скомпилировал с очень сильной оптимизацией, двоичная "куча" получила огромное повышение. В моих тестах "куча" Fibonacci только превзошла двоичную "кучу" по характеристикам, когда график был невероятно большим и плотным, например:

Generating graph...10000 vertices, 20000000 edges.
Running Dijkstra's with binary heap...1.46 seconds.
Running Dijkstra's with Fibonacci heap...1.31 seconds.
Speedup = 1.1145.

Насколько я понимаю, это заходит в принципиальные различия между "кучей" Fibonacci и двоичной "кучей". Единственное реальное теоретическое различие между этими двумя структурами данных - то, что "куча" Fibonacci поддерживает ключ уменьшения в (амортизируемом) постоянном времени. С другой стороны, двоичная "куча" получает большую производительность от их реализации как массив; использование явной структуры указателя означает, что "куча" Fibonacci переносит огромный хит производительности.

Поэтому для пользы из "кучи" Fibonacci на практике необходимо использовать их в приложении где decrease_ ключи являются невероятно частыми. С точки зрения Dijkstra это означает, что базовый график является плотным. Некоторые приложения могли быть внутренне decrease_ ключевой интенсивный; я хотел попробовать Nagomochi-Ибараки сокращенный из минимума алгоритм , потому что, по-видимому, он генерирует много decrease_ ключи, но это было слишком много усилия получить работу сравнения синхронизации.

Предупреждение : Я, возможно, сделал что-то не так. Можно хотеть попытаться воспроизвести эти результаты сами.

Теоретическое примечание : улучшенная производительность Fibonacci сваливает decrease_ в кучу; ключ важен для теоретических приложений, таков как время выполнения Dijkstra. Fibonacci помещает в "кучу", также превосходят двоичный файл по характеристикам, сваливает вставку в кучу и объединяющийся (оба амортизировали постоянно-разовый для "кучи" Fibonacci). Вставка чрезвычайно не важна, потому что она не влияет на время выполнения Dijkstra, и довольно легко изменить двоичную "кучу", чтобы также иметь, вставляют в амортизируемое постоянное время. Слияние в постоянное время является фантастическим, но не относится к этому приложению.

Личное сообщение : мой друг и я однажды написали работу, объяснив новую приоритетную очередь, которая попыталась копировать (теоретическое) время выполнения "кучи" Fibonacci без их сложности. Работа никогда не публиковалась, но мой соавтор действительно реализовывал двоичную "кучу", "кучу" Fibonacci и нашу собственную приоритетную очередь для сравнения структур данных. Графики результатов эксперимента указывают, что "куча" Fibonacci немного превзошла двоичную "кучу" по характеристикам с точки зрения общих сравнений, предположив, что "куча" Fibonacci будет работать лучше в ситуации, где стоимость сравнения превышает наверху. К сожалению, я не имею код в наличии, и по-видимому в Вашей ситуации сравнение является дешевым, таким образом, эти комментарии релевантны, но не непосредственно применимы.

Кстати, я настоятельно рекомендую попытку соответствовать времени выполнения "кучи" Fibonacci с Вашей собственной структурой данных. Я нашел, что просто переосмыслил "кучу" Fibonacci сам. Прежде чем я думал, что все сложности "кучи" Fibonacci были некоторыми случайными идеями, но позже я понял, что они были все естественными и довольно принудительными.

133
ответ дан Guilherme Torres Castro 31 January 2012 в 21:33
поделиться

Кнут провел сравнение между кучей Фибоначчи и двоичными кучами для минимальных остовных деревьев еще в 1993 году для своей книги Стэнфорд Graphbase . Он обнаружил, что фибоначчи на 30–60% ниже, чем двоичные кучи при тестируемых размерах графов, 128 вершин с различной плотностью.

Исходный код находится на C (или, скорее, CWEB, который является крестиком между C, math и TeX) в разделе MILES_SPAN.

32
ответ дан 23 November 2019 в 22:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: