Re[15]: cpp и математика
От: Erop Россия  
Дата: 09.08.16 08:38
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Ну а я как-то обхожусь без этого.

Ну задачи просто разные...

BFE>Значит я не понял, что значит склеивать.


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


BFE>О звёзды! Это что? В списке всегда хранится один лишний элемент с аллоцированной памятью под пользовательские данные? Какой кошмар...

BFE>Похоже, что авторы, таки, реализовали эту абсурдную идею с графом из одной вершины.
BFE>Нет, ну я не могу отвечать за это извращение. Мало ли, что там под капот засунули...

Просто ты предвзят. Я уверен, что если ты попробуешь, то твоей квалификации хватит реализовать такой список БЕЗ ОВЕРХЕДА...
  не подсматривай
class list_node_base {
publc:
    list_node_base() { next = prev = this; }
    ~list_node_base() { next->prev = prev; prev->next = next; }

    list_node_base* get_next() { retrn assert_not_null( next ); }
    list_node_base* get_prev) { retrn assert_not_null( prev ); }

    bool is_along() const { return prev == this; } 
    void insert_after_me( list_node_base* node )
    {
        assert( node != 0 && node->is_along() ); 
        node->prev = this;
        node->next = next;
        next->prev = node;
        next = node;
    }
    void detach()
    {
        next->prev = prev;
        prev->next = next;
        prev = next = this;
    }
 
    
protected:
    list_node_base( list_node_base* prev_node ) : prev( prev_node ), next( prev_node->next )
        { prev_node->next = next->prev = this; }
    static list_node_base* assert_not_null( list_node_base* p ) { assert( p != 0 ); return p; }
private:
    list_node_base* prev;
    list_node_base* next;    
};

template<typeneme T>
class my_list : {
public:
    class iterator {
    public:
        iterator( list_node_base* p ) : node( p ) { assert( p != 0 ); }
        T* get_ptr() { assert( node != 0 && !node->is_along() ); return static_cast<T*>( node ); }
        T& operator*() { return get_ptr(); }
        // тут сам допишешь
    private:
        list_node_base* node;
    };
    class riterator {
        // тут сам допишешь
    };
    // константные итераторы тоже сам ;)

    iterator end() { return &list_data; }    
    iterator begin() { return list_data.get_next(); }    
    
    riterator end() { return &list_data; }    
    riterator begin() { return list_data.get_prev(); }    
private:
    class node : public list_node_base {
    public:
        T data;
    
        // тут сам допишешь
    };
    list_node_base    list_data;
};


BFE>А можно и не рассматривать...


От задач зависит...
Если ты про графы не знаешь, а такой взгляд в задаче полезен, то упс.
Просто в твоей области графы, видимо, не особо нужны. Хотя мне не ясно, как ты искал путь, без чего-то вроде A*, хотя бы и самопального.

BFE>Не, анализ — это не то...

BFE>Анализ — это не для пользователей, а для аналитиков. Аналитики любят красивые картинки...
То. На графе связей пользователя можно, например, обучить классификатор, который отличает ботов от реальных людей...

E>>Почему поиск цикла в таком списке -- это алгоритм на графе, а поиск цикла в ГПСЧ -- нет? Алгоритм-то тот же?

BFE>Потому, что список существует как структура и к ней применяется алгоритм. А при поиске цикла в ГПСЧ нам сама структура не нужна, насколько я понимаю.

И что? Там у структуры мы вызываем метод get_next_node_ptr(), а тут вызываем метод get_next_seed()/
Оба возвращают некое Id узла. В чём разница для алгоритма поиска цикла в списке?

BFE>И они крайне редко нужны на практике.


Зависит от практики
Если, например, формошлёпить для интранета, то математика вообще не нужна, IMHO,..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[18]: cpp и математика
От: B0FEE664  
Дата: 09.08.16 10:55
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Я посмотрел в исходниках libstdc++ — насколько я распарсил, там именно так — последний узел имеет только два указателя, без места под данные.

Похоже на то.

EP>В других реализациях может быть по-другому.

Ага:
_Value_type _Myval;    // the stored value, unused if head


BFE>>А почему вообще нельзя обойтись без этой ноды?

EP>Ты имеешь в виду использовать вместо неё nullptr? Не получится — список двусвязный, мы можем взять std::prev от .end(). Можно конечно попробовать без дополнительного узла, но будет сложнее, а главное медленнее.
Есть варианты. Например, .end() итератор может хранить указатель на сам List, а List может иметь хранить указатель на last. Но придётся заводить отдельный тип, который должен будет мимикрировать под вид обычного итератора...

EP>Да и проблемы в дополнительной ноде нет никакой — она хранится по значению в std::list, и содержит только два указателя которые нужны в любом случае.

Согласен.
И каждый день — без права на ошибку...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.