Re[5]: поправка
От: Dr.Gigabit  
Дата: 21.10.04 11:45
Оценка:
Здравствуйте, <Аноним>, Вы писали:


А>Написание сбалансированного третичного дерева оставим студентам в качестве домашнего задания



#define MAXWORDS 250000
#define MAXCHARS 3000000
char space[MAXCHARS], *a[MAXWORDS];

void rinsall(char *a[], int n)
{   int m;
    if (n < 1) return;
    m = n/2;
    insert(a[m]);  // insert - ф-ция вставки
    rinsall(a, m);
    rinsall(a + m+1, n-m-1);
}

void main()
{
   char *s = space;
    int    n = 0
    a[0] = s;
    FILE *fp = fopen("file.txt");
     while ((i = getc(fp)) != EOF) 
    {    
        if (i == '\n')
        {
            *s++ = 0;
           a[++n] = s;
       }
        else
        *s++ = i;
    }
    rinsall(a, n);    
}


... << RSDN@Home 1.1.4 @@subversion >>
Re[4]: ternary tree / minimal perfect hash
От: c-smile Канада http://terrainformatica.com
Дата: 24.10.04 23:08
Оценка:
Здравствуйте, Dmitry521, Вы писали:

D>Мне кажется она неверно считает HAMMING DISTANCE.



D>woman, man, many, wman, mwan

D>искал слово man.
D>результаты
D>d = 1 man, many Я считаю должно было быть — man, many, mwan, wman

По определению hamming distance
wman ^ man = 4 и
mwan ^ man = 3

Все вроде правильно. Для целей spell check имхо надо еще SOUNDEX
на result_set напускать.
Re[2]: ternary tree / minimal perfect hash
От: c-smile Канада http://terrainformatica.com
Дата: 24.10.04 23:22
Оценка:
Здравствуйте, Dr.Gigabit, Вы писали:

DG>Здравствуйте, c-smile, Вы писали:


DG>
DG> node_index  insert(node_index nid, const CHAR *s)
DG>    { 
DG>       if (nid >= total_nodes()) 
DG>       {
DG>            node n; n.splitchar = *s;
DG>            nodes.push(n);
DG>            nid = nodes.last_index();        // здесь ошибка
DG>         }
DG>


В моем array метод last_index() возвращает int — последний валидный индекс в массиве или -1.
node_index это unsigned int; должно приводится без сайдэффектов здесь.


DG>Может быть подскажете, что не так делаю?

DG>И еще вопрос параллелльно : на сколько ваш array по быстродействию выигрывает у vector? Думаю, измерения проводились...

Мой массив в его ьекущей инкарнации работает с абсолютно той же скоростью что и std::vector.

В ситуациях например типа array< smart_ptr<something> > мой работает на insert/append быстрее. Иногда значительно. Все мои классы позиционно независимы поэтому я могу себе позволить memcpy.
Что требует определенной дисциплины. Поэтому я его и не выкладываю.
Re[3]: ternary tree / minimal perfect hash
От: Dr.Gigabit  
Дата: 24.10.04 23:56
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, Dr.Gigabit, Вы писали:


DG>>Здравствуйте, c-smile, Вы писали:


DG>>
DG>> node_index  insert(node_index nid, const CHAR *s)
DG>>    { 
DG>>       if (nid >= total_nodes()) 
DG>>       {
DG>>            node n; n.splitchar = *s;
DG>>            nodes.push(n);
DG>>            nid = nodes.last_index();        // здесь ошибка
DG>>         }
DG>>


CS>В моем array метод last_index() возвращает int — последний валидный индекс в массиве или -1.

CS>node_index это unsigned int; должно приводится без сайдэффектов здесь.

Смотрим array.h:
const element&
last_index () const
{
return _size — 1;
}
Видимо, вместо const element& нужно int? Подправил — работает
Еще по одному вопросу не могу сообразить (что-то в 3 часа ночи не думается)

    tool::array<unsigned int> resultSet;
    TST.insert("andy");
    TST.neighbour_search("aldy",1,resultSet);
    cout << resultSet[0] << endl;


Выводит 1. Каким образом слова отображать-то?
В своей реализации TST я использую vector<char*> resultSet;
А как с dword'ом быть?
... << RSDN@Home 1.1.4 @@subversion >>
Re[4]: ternary tree / minimal perfect hash
От: c-smile Канада http://terrainformatica.com
Дата: 26.10.04 00:07
Оценка:
Здравствуйте, Dr.Gigabit, Вы писали:

DG>Смотрим array.h:

DG> const element&
DG> last_index () const
DG> {
DG> return _size — 1;
DG> }
DG>Видимо, вместо const element& нужно int? Подправил — работает
DG>Еще по одному вопросу не могу сообразить (что-то в 3 часа ночи не думается)

У-у-у, какая древность, но все равно спасибо, надо опять на SF идти изменять а там все не просто.

Да конечно нужно так:
inline const element&  last  () const;
  inline int last_index () const
  {
    return _size - 1;
  }



DG>Выводит 1. Каким образом слова отображать-то?

DG>В своей реализации TST я использую vector<char*> resultSet;
DG>А как с dword'ом быть?


class lookup {

   ternary_tree<char> index;
   vector<string>     values; 

   void insert(const char* s)
   {
     int i = index.insert(s) - 1;
     if(i >= values.size()) 
     {
       assert(i == values.size()); 
       values.push_back(s);
     }
   }
   string get_value_by_id(int idx) const { return (idx > 0)? values[idx-1] : "{unknown}"; }
};
Re: ternary tree / minimal perfect hash
От: Аноним  
Дата: 26.11.04 21:13
Оценка:
Здравствуйте, c-smile, Вы писали:


CS>Второй вариант — воспользоваться предлагаемой имплементацией ternary tree [2]:

[skiped]

Не могли бы вы прояснить такую вещь:
При записи всех узлов в бинарный файл, количество записываемых узлов 107184
(значение, возвращаемое total_nodes() ). Но в одном из узлов lokid имеет значение 4294967295

В то же время при проецировании бинарного файла, в который предварительно записаны все узлы, в память,
их количество 3435973836 (проверяю в цикле, пока указатель не NULL)

Как locid может иметь значение, большее кол-ва узлов? Или я где-то не прав?

Спасибо.
Re: ternary tree / minimal perfect hash
От: CreatorCray  
Дата: 07.09.05 21:40
Оценка: 1 (1) +1
Здравствуйте, c-smile, Вы писали:

Есть серьезный недостаток — требовательность к памяти. Чем длиннее ключ — тем больше хавает. А если ключи еще и различаются в начале — вообще абзац.
Проверял практическим способом
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[2]: ternary tree / minimal perfect hash
От: c-smile Канада http://terrainformatica.com
Дата: 08.09.05 03:37
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, c-smile, Вы писали:


CC>Есть серьезный недостаток — требовательность к памяти. Чем длиннее ключ — тем больше хавает. А если ключи еще и различаются в начале — вообще абзац.


Ну в общем и целом утверждение "требовательность к памяти" справедливо для любой конструкции такого рода.

Для hash tables нужно тоже где-то ключи хранить.
Причем если ключи примерно такого типа:

"Маша мыла Раму"
"Маша мыла Мессершмит"
"Маша мыла Вову"

То оверхед у hash-table по памяти будет больше.
Re[3]: ternary tree / minimal perfect hash
От: CreatorCray  
Дата: 08.09.05 10:38
Оценка: 1 (1)
Здравствуйте, c-smile, Вы писали:

CS>Ну в общем и целом утверждение "требовательность к памяти" справедливо для любой конструкции такого рода.

CS>Для hash tables нужно тоже где-то ключи хранить.
Но там то ключи фиксированного размера = размеру хеша. А хеш можно посчитать по ооочень длинной строке.

CS>Причем если ключи примерно такого типа: [skipped]

CS>То оверхед у hash-table по памяти будет больше.

Это понятно, речь не об этом. Сравнивать его лучше с Patricia как с близким по принципу действия.
Впрочем вы с cranky и так уже пересеклись

Когда я запхал в него и в patricia телефонный справочник (номер + фио как один ключ — все ключи уникальны) то ternary отожрал больше гига памяти. Тут просто трабл в том, что на 1 символ ключа выделяется +3*sizeof (uint). И в ситуации, когда ключи различаются в самом начале (Ex: "123 мама мыла раму" "124 мама мыла раму" "223 мама мыла раму" и т.д.) то оверхед получается максимальным — все "хвосты" ключей добавляются в nodes, а это 13 байт на char.
Также этот алго проигрывает в случае если ключи — пути к файлам. К примеру список всех файлов HDD с путями: 99519 строк. Ternary: 32.9 Mb 15508 CPU ticks per lookup, Patricia: 23.8 Mb 3811 CPU ticks per lookup.
Но на простых текстах (выборка всех слов из 400 мб. текстовика: слил много книг в 1 txt файл) Ternary рвет patricia с отрывом в 3-5 раз по скорости и почти в 2 раза по памяти. Но при этом следует учесть что Patricia хранит имена ключей.

IMHO ternary алго отличный, но область применения ограничена по причине зависимости потребления ресурсов от входных данных.
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[4]: ternary tree / minimal perfect hash
От: c-smile Канада http://terrainformatica.com
Дата: 08.09.05 15:56
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, c-smile, Вы писали:


CS>>Ну в общем и целом утверждение "требовательность к памяти" справедливо для любой конструкции такого рода.

CS>>Для hash tables нужно тоже где-то ключи хранить.
CC>Но там то ключи фиксированного размера = размеру хеша. А хеш можно посчитать по ооочень длинной строке.

Но сами строки в полном виде ты хранить тоже обязан для разрешения коллизий.
Так что хэш таблица как структура тоже зависит от длины ключа.

CS>>Причем если ключи примерно такого типа: [skipped]

CS>>То оверхед у hash-table по памяти будет больше.

CC>Это понятно, речь не об этом. Сравнивать его лучше с Patricia как с близким по принципу действия.

CC>Впрочем вы с cranky и так уже пересеклись

CC>Когда я запхал в него и в patricia телефонный справочник (номер + фио как один ключ — все ключи уникальны) то ternary отожрал больше гига памяти. Тут просто трабл в том, что на 1 символ ключа выделяется +3*sizeof (uint). И в ситуации, когда ключи различаются в самом начале (Ex: "123 мама мыла раму" "124 мама мыла раму" "223 мама мыла раму" и т.д.) то оверхед получается максимальным — все "хвосты" ключей добавляются в nodes, а это 13 байт на char.


[skiped].

На самом деле возможны варианты.

1) Хранить хвосты после последних развилок как фрагменты строк т.е. получается 1/2 байта (char/wchar) на 1 символ.
2) Ввести ограничение на длину ключа — а дальше collision tables.

Да, еще нужно обратить внимание что алгоритм зависит от способа наполнения — если ключи
поступают в случайном порядке то дерево получается более отимальным чем в случае с "по порядку"
Re[5]: ternary tree / minimal perfect hash
От: CreatorCray  
Дата: 08.09.05 21:59
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Но сами строки в полном виде ты хранить тоже обязан для разрешения коллизий.

CS>Так что хэш таблица как структура тоже зависит от длины ключа.
Верно. Упустил из виду...

CS>На самом деле возможны варианты.


CS>1) Хранить хвосты после последних развилок как фрагменты строк т.е. получается 1/2 байта (char/wchar) на 1 символ.

Верно. Но надо уже смотреть на реализацию: ведь тогда как я понимаю надо будет при вставке если возникнет необходимость эти хвосты разрезАть.

CS>2) Ввести ограничение на длину ключа — а дальше collision tables.

ИМХО это уже неправильно.
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re: ternary tree / minimal perfect hash
От: korzhik Россия  
Дата: 21.03.06 21:53
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Второй вариант — воспользоваться предлагаемой имплементацией ternary tree [2]:


CS>Замечания по имплементации:

CS>1) Я использую свой array который может быть легко заменен на std::vector

Попал в интересную ситуацию...
следующий код нормально отрабатывает в Debug, в релизе валится.
Компилятор VC6, VC2003 Release (/O1 или /O2)
--------------------------------------------------
Прошу прощения за столь длинный код, но валится именно на таком количестве.
Если заменить std::vector на std::deque то всё нормально.
Если удалить хотя бы одну строчку вставки ttree.insert(...); то тоже всё нормально.
Вот такие дела....
Сам не смог разобраться...
---------------------------------------------------
//-------------------------------------------------
#include <vector>
#include <cassert>
//------------------------------------------------
namespace tool 
{
    typedef unsigned int dword;

    template <typename CHAR>
    class ternary_tree
    {
        typedef unsigned int node_index;
    public:
        ternary_tree(): max_no(0) {}

        dword insert(const CHAR *s)
        {
            return (dword)nodes[insert(0, s)].eqkid;
        }

        // returns n[1..max_no] or zero if not found
        dword search(const CHAR *s) const
        {   
            node_index nid = 0; // root index;
            while (nid < total_nodes()) 
            {
                const node& n = nodes[nid];
                if (*s < n.splitchar)
                    nid = n.lokid;
                else if(*s > n.splitchar)
                    nid = n.hikid;
                else //(*s == p->splitchar) 
                {
                    if (*s++ == 0)
                        return n.value();
                    nid = n.eqkid;
                } 
            }
            return 0;
        }

    protected: 
        struct node 
        {
            CHAR       splitchar;
            node_index lokid;
            node_index eqkid;
            node_index hikid;

            node() : splitchar(0), lokid(-1), eqkid(-1), hikid(-1) {}

            dword value() const 
            {
                assert(splitchar == 0);
                return (dword)eqkid;
            }
            void value(dword v)  
            {
                assert(splitchar == 0);
                eqkid = (node_index)v;
            }
        };

        std::vector<node> nodes;
        dword             max_no;

        size_t     total_nodes() const { return nodes.size(); }

        node_index insert(node_index nid, const CHAR *s)
        { 
            if (nid >= total_nodes()) 
            {
                node n; n.splitchar = *s;
                nodes.push_back(n);
                nid = nodes.size() - 1; 
            }
            const node& n = nodes[nid];
            if (*s < n.splitchar)
                nodes[nid].lokid = insert(n.lokid, s);
            else if(*s > n.splitchar)
                nodes[nid].hikid = insert(n.hikid, s);
            else //*s == p->splitchar 
            {
                if (*s == 0)
                //"...we'll exploit the fact that a node with a 
                // null splitchar cannot have an eqkid, 
                // and store the data in that field."
                    nodes[nid].value(++max_no);
                else
                    nodes[nid].eqkid = insert(n.eqkid, ++s);
            }
            return nid;
         }

        static int length(const CHAR* s)
        {
            const CHAR* ps = s; while(*s) ++s; return s - ps;
        }
    };
}

int main()
{
    tool::ternary_tree<char> ttree;

    ttree.insert("accent-height");
    ttree.insert("accumulate");
    ttree.insert("alignment-baseline");
    ttree.insert("alphabetic");
    ttree.insert("amplitude");
    ttree.insert("animate");
    ttree.insert("arabic-form");
    ttree.insert("ascent");
    ttree.insert("attributeType");
    ttree.insert("azimuth");
    ttree.insert("baseFrequency");
    ttree.insert("baseProfile");
    ttree.insert("baseline-shift");
    ttree.insert("bbox");
    ttree.insert("bias");
    ttree.insert("by");
    ttree.insert("calcMode");
    ttree.insert("cap-height");
    ttree.insert("class");
    ttree.insert("clip");
    ttree.insert("clip-path");
    ttree.insert("clip-rule");
    ttree.insert("clipPathUnits");
    ttree.insert("color");
    ttree.insert("color-interpolation");
    ttree.insert("color-interpolation-filters");
    ttree.insert("color-profile");
    ttree.insert("color-rendering");
    ttree.insert("contentScriptType");
    ttree.insert("contentStyleType");
    ttree.insert("cursor");
    ttree.insert("cx");
    ttree.insert("cy");
    ttree.insert("d");
    ttree.insert("descent");
    ttree.insert("diffuseConstant");
    ttree.insert("direction");
    ttree.insert("display");
    ttree.insert("divisor");
    ttree.insert("dominant-baseline");
    ttree.insert("dur");
    ttree.insert("dx");
    ttree.insert("dy");
    ttree.insert("edgeMode");
    ttree.insert("elevation");
    ttree.insert("enable-background");
    ttree.insert("end");
    ttree.insert("exponent");
    ttree.insert("externalResourcesRequired");
    ttree.insert("feColorMatrix");
    ttree.insert("feComposite");
    ttree.insert("feGaussianBlur");
    ttree.insert("feMorphology");
    ttree.insert("feTile");
    ttree.insert("fill");
    ttree.insert("fill-opacity");
    ttree.insert("fill-rule");
    ttree.insert("filter");
    ttree.insert("filterRes");
    ttree.insert("filterUnits");
    ttree.insert("flood-color");
    ttree.insert("flood-opacity");
    ttree.insert("font-family");
    ttree.insert("font-size");
    ttree.insert("font-size-adjust");
    ttree.insert("font-stretch");
    ttree.insert("font-style");
    ttree.insert("font-variant");
    ttree.insert("font-weight");
    ttree.insert("format");
    ttree.insert("from");
    ttree.insert("fx");
    ttree.insert("fy");
    ttree.insert("g1");
    ttree.insert("glyph-name");
    ttree.insert("glyph-orientation-horizontal");
    ttree.insert("glyph-orientation-vertical");
    ttree.insert("glyphRef");
    ttree.insert("gradientTransform");
    ttree.insert("gradientUnits");
    ttree.insert("hanging");
    ttree.insert("height");
    ttree.insert("horiz-adv-x");
    ttree.insert("horiz-origin-y");
    ttree.insert("id");
    ttree.insert("ideographic");
    ttree.insert("image-rendering");
    ttree.insert("in");
    ttree.insert("in2");
    ttree.insert("intercept");
    ttree.insert("k");
    ttree.insert("k1");
    ttree.insert("k2");
    ttree.insert("k3");
    ttree.insert("k4");
    ttree.insert("kernelMatrix");
    ttree.insert("kernelUnitLength");
    ttree.insert("kerning");
    ttree.insert("keyPoints");
    ttree.insert("keySplines");
    ttree.insert("keyTimes");
    ttree.insert("lang");
    ttree.insert("lengthAdjust");
    ttree.insert("letter-spacing");
    ttree.insert("lighting-color");
    ttree.insert("limitingConeAngle");
    ttree.insert("local");
    ttree.insert("marker");
    ttree.insert("marker-end");
    ttree.insert("marker-mid");
    ttree.insert("marker-start");
    ttree.insert("markerHeight");
    ttree.insert("markerUnits");
    ttree.insert("markerWidth");
    ttree.insert("mask");
    ttree.insert("maskContentUnits");
    ttree.insert("maskUnits");
    ttree.insert("mathematical");
    ttree.insert("max");
    ttree.insert("media");
    ttree.insert("method");
    ttree.insert("min");
    ttree.insert("mode");
    ttree.insert("name");
    ttree.insert("numOctaves");
    ttree.insert("offset");
    ttree.insert("opacity");
    ttree.insert("operator");
    ttree.insert("order");
    ttree.insert("orient");
    ttree.insert("orientation");
    ttree.insert("origin");
    ttree.insert("overflow");
    ttree.insert("overline-position");
    ttree.insert("overline-thickness");
    ttree.insert("panose-1");
    ttree.insert("path");
    ttree.insert("pathLength");
    ttree.insert("patternContentUnits");
    ttree.insert("patternTransform");
    ttree.insert("patternUnits");
    ttree.insert("pointer-events");
    ttree.insert("points");
    ttree.insert("pointsAtX");
    ttree.insert("pointsAtY");
    ttree.insert("pointsAtZ");
    ttree.insert("preserveAlpha");
    ttree.insert("preserveAspectRatio");
    ttree.insert("primitiveUnits");
    ttree.insert("r");
    ttree.insert("radius");
    ttree.insert("refX");
    ttree.insert("refY");
    ttree.insert("rendering-intent");
    ttree.insert("repeatCount");
    ttree.insert("repeatDur");
    ttree.insert("requiredExtensions");
    ttree.insert("restart");
    ttree.insert("result");
    ttree.insert("rotate");
    ttree.insert("rx");
    ttree.insert("ry");
    ttree.insert("scale");
    ttree.insert("seed");
    ttree.insert("shape-rendering");
    ttree.insert("slope");
    ttree.insert("spacing");
    ttree.insert("specularConstant");
    ttree.insert("specularExponent");
    ttree.insert("spreadMethod");
    ttree.insert("startOffset");
    ttree.insert("stdDeviation");
    ttree.insert("stemh");
    ttree.insert("stemv");
    ttree.insert("stitchTiles");
    ttree.insert("stop-color");
    ttree.insert("stop-opacity");
    ttree.insert("strikethrough-position");
    ttree.insert("strikethrough-thickness");
    ttree.insert("stroke");
    ttree.insert("stroke-dasharray");
    ttree.insert("stroke-dashoffset");
    ttree.insert("stroke-linecap");
    ttree.insert("stroke-linejoin");
    ttree.insert("stroke-miterlimit");
    ttree.insert("stroke-opacity");
    ttree.insert("stroke-width");
    ttree.insert("style");
    ttree.insert("surfaceScale");
    ttree.insert("systemLanguage");
    ttree.insert("tableValues");
    ttree.insert("target");
    ttree.insert("targetX");
    ttree.insert("targetY");
    ttree.insert("text-anchor");
    ttree.insert("text-decoration");
    ttree.insert("text-rendering");
    ttree.insert("textLength");
    ttree.insert("title");
    ttree.insert("to");
    ttree.insert("transform");
    ttree.insert("type");
    ttree.insert("u1");
    ttree.insert("u2");
    ttree.insert("underline-position");
    ttree.insert("underline-thickness");
}
Re: ternary tree / minimal perfect hash
От: Аноним  
Дата: 02.10.06 17:08
Оценка: 2 (1)
msvc.net 2003 с оптимизацией включенной вылетает с покорупченным хипом.

я подозреваю что дело в


nodes[nid].hikid = insert(n.hikid, s);


компилятор падклюка сперва вычисляет адрес nodes[nid].hikid а потом делает insert, кусок памяти пеезжает и оно падает.
заменил на

 node_index i = insert(n.lokid, s);
 nodes[nid].lokid = i;


стало работать.. кто не прав -- c-smile или компилятор? или это у меня что-то не так?