Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 09:58
Оценка: :)))
Раньше на raw-ptr узел дерева, если говорить о двоичном варианте, выглядел
struct TNode
{
   TAtrributes m_Atrributes;

   TNode* m_pLeftChild;
   TNode* m_pRightChild;

   TNode* m_pParent;
};



При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?

p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели
Re: Реализация дерева средствами с++11
От: Кодт Россия  
Дата: 18.04.16 11:37
Оценка: 8 (2)
Здравствуйте, _hum_, Вы писали:

__>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


Если делать по-человечески, то все узлы дерева должны использовать общий счётчик ссылок: пока есть хоть один указатель на хоть один узел дерева, всё дерево остаётся живым.

Кстати, shared_ptr такое умеет: держать счётчик на один объект, а указатель на другой, жизненно связанный с ним.
struct A {
  B subordinate;
};

shared_ptr<A> pa = make_shared<A>();
shared_ptr<B> pb(&pa->subordinate, pa);
pa.reset(); // но pb, а через него и весь объект A, продолжает жить!
pb.reset(); // теперь А умрёт и по-человечески убъёт B своим деструктором

В нашем случае это ненужное знание, но — так, к слову, вдруг кто не знает. Фича-то полезная.

Проблема возникает тогда, когда мы отцепляем поддерево. Теперь указатели на отцепленное поддерево должны мысленно переключиться на новый счётчик.
И тут есть два варианта решений
— или пропатчить все указатели (что теоретически возможно, если это linked_ptr'ы — но, понятное дело, это не потокобезопасно; с другой стороны, расковыр дерева должен происходить в критической секции, так что какие-то компромиссы здесь могут быть)
— или сделать довольно хитрую механику подсчёта ссылок, больше похожую на интрузивные указатели.

Давайте рассмотрим это поподробнее.

Пусть каждый узел знает, сколько на него есть указателей со стороны — как непосредственно на него, так и на нижележащие. Внутренние указатели в зачёт не идут.
struct Node {
  Node *up, *lt, *rt;
  unsigned refcount;
};

bool is_alive(Node const* node) {
  assert(node);
  return node->up || node->refcount;
}

void delete_subtree(Node* node) {
  if (!node) return;
  delete_subtree(node->left);
  delete_subtree(node->right);
  delete node;
}

void try_delete(Node* node) {
  if (node && !is_alive(node)) delete_subtree(node);
}

void incref_impl(Node* node, int delta) {
  if (delta == 0) return;
  Node* top = nullptr;
  // бежим вверх по дереву
  while(node) {
    top = node;
    node->refcount += delta;
    node = node->up;
  }
  // если корень дерева отсох, удаляем его
  if (delta < 0) try_delete(node);
}

void intrusive_addref(Node* node) { incref_impl(node, +1); }
void intrusive_decref(Node* node) { decref_impl(node, -1); }

void cut_left(Node* node) {
  assert(node && node->left);
  Node* left = node->left;
  // разрываем связь
  left->up = nullptr;
  node->left = nullptr;
  // и отнимаем ставшие неродными счётчики
  incref_impl(node, -left->refcount);
  try_delete(left);
}

void attach_left(Node* node, Node* left) {
  assert(node && !node->left);
  assert(left && !left->up);
  // добавляем счётчики
  incref_impl(node, +left->refcount);
  // и создаём связь
  left->up = node;
  node->left = left;
}

(disclaimer. код эскизный, чисто для иллюстрации; писал "с листа", мог и напутать, поэтому не судите строго)

Проблема здесь в том, что цена каждого присоединения указателя — O(H), где H — высота дерева. Плюс неизбежные кешмиссы.

Другой способ — это пусть каждый узел считает только свои внешние ссылки, но тогда процедура проверки удаления потребует обхода поддерева.
bool is_alive(Node* node) {
  return node->refcount || (node->left && is_alive(node->left)) || (node->right && is_alive(node->right));
}


Между этими двумя крайностями, конечно, можно и нужно найти компромиссы. Например, сделать ключевые узлы, чтобы уменьшить расстояние забегов в проверках. Но такие решения будут выглядеть гораздо громоздче.
Перекуём баги на фичи!
Re[6]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 18.04.16 10:50
Оценка: :))
Здравствуйте, Kernan, Вы писали:

K>Здравствуйте, _hum_, Вы писали:


__>>>>ясно же, зачем, чтобы иметь возможность выполнения быстрой вставки, например.

K>>>Что такое "быстрая вставка" в дереве? Любая вставка в дерево начинается с поиска.
__>>insert(TNode* pNodeWhere) за O(1)

K>И куда ты это вставишь? Мне кажется есть только одн оместо для этого .


список — частный случай дерева, но ставка там не в одно место: std::list::insert

__>>>>в том смысле, что в "будущем ими пользоваться практически не будут, и все заменят умные"

K>>>Ну ерунда же.
__>>"ваши доказательства" (с)
K>Совместимость с С.

"Ну ерунда же." (с) (речь не про отмену сырых указателей, а про замену их в практике программирования умными)
Re[3]: Реализация дерева средствами с++11
От: Ops Россия  
Дата: 16.04.16 22:51
Оценка: +1
Здравствуйте, _hum_, Вы писали:

__>проблема возникла из : нужно организовать дерево, которое бы можно было сериализовать с помощью библиотеки cereal (она самая лекговесная и удобная из виденных мною). последняя умеет работать только с умными указателями.


А если не сериализовывать этот указатель вообще? А после (или в процессе, смотря как оно сделано) десереализации обойти дерево и присвоить нужные значения.
Библиотеку не знаю, так что все умозрительно.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[18]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 18.04.16 08:21
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>выделенное не понял — какой перерасход памяти?


E>Ну я так понял, что ты под сериализацию строишь другое дерево? Или что ты делаешь вместо прошивания дерева руками после загрузки?


аа, ну так озу нас не волнует
Re[3]: Реализация дерева средствами с++11
От: Кодт Россия  
Дата: 19.04.16 10:31
Оценка: +1
Здравствуйте, T4r4sB, Вы писали:

К>>Если делать по-человечески, то все узлы дерева должны использовать общий счётчик ссылок: пока есть хоть один указатель на хоть один узел дерева, всё дерево остаётся живым.


TB>Почему?

TB>Это нужно далеко не во всех задачах.

Если дерево извне представлено цельным объектом, то должны быть владеющие указатели на дерево (не на корневой узел, а именно на дерево, распоряжающееся корневым узлом и всеми прочими узлами) и голые указатели/итераторы на узлы. Которые инвалидируются, если соответствующие узлы умерли (или даже если они перемещены каким-то внезапным способом — тут уже всё зависит от контракта итератора).
Самое малое, что можно сделать в этих условиях — это внутренние связи сделать на shared_ptr/weak_ptr, чтобы получить автоматическое разрушение, а внешние указатели (из итераторов) — на weak_ptr, чтобы инвалидацию можно было диагностировать.

Если же нужно более-менее локально работать с поддеревьями, то придётся изобретать изощрённые механизмы сборщика мусора.
Будь то каскадные счётчики, или предсмертный обход, или ещё что-то.

И, возможно, смотреть в сторону чисто функциональных структур данных — версионных неизменяемых деревьев. Чтобы, если в одном месте ковыряемся, это не затронуло другие места...
Перекуём баги на фичи!
Re: Реализация дерева средствами с++11
От: Stanislav V. Zudin Россия  
Дата: 16.04.16 12:01
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Раньше на raw-ptr узел дерева, если говорить о двоичном варианте, выглядел


__>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


Предлагаю "ход конём". Заменить указатели на индексы в массиве.

    enum { NONE = -1 };

    typedef int NODE;                   //!< Узел дерева
    typedef int ATTR;                   //!< Атрибут узла

    class Document
    {
        ... ...

        struct NodeInfo
        {
            NAMEREF name;               // Ссылка на имя
            NODE next,                  // Следующий
                 prev,                  // Предыдущий
                 parent,                // Родительский узел
                 child;                 // Первый дочерний узел
            ATTR attr;                  // Первый атрибут узла
            VALREF value;               // Ссылка на значение

            NodeInfo()
                : name(NONE)
                , next(NONE), prev(NONE)
                , parent(NONE), child(NONE)
                , attr(NONE), value(NONE) {}
        };

        typedef std::vector<NodeInfo> TNodes;
        // ------------------------------------------------------------------
        NODE m_RootNode;                // Корневой узел
        NODE m_NodeFreeList;            // Список удаленных узлов

        TNodes m_InfoNode;              // Свойства узлов

        ... ...
    };



Для навигации можно использовать итератор:

    class inode
    {
    public:
        inode();
        inode(Document* pdoc, NODE n);
        inode(const inode& n);

        LPCTSTR getName() const;
        LPCTSTR getValue() const;

        void setValue(LPCTSTR valN);
        void setValue(LPCTSTR valN, size_t length);

        iattr getAttrs() const;
        iattr getAttr(LPCTSTR name) const;

        inode getChild() const;
        inode getChild(LPCTSTR name) const;
        inode getParent() const;
        inode getNext() const;
        inode getPrev() const;

        const inode& operator++();
        bool end() const;

        NODE id() const;

        //! Добавить дочерний узел после <prev>
        inode addNode(LPCWSTR name, NODE prev);

        //! Задать значение атрибута
        iattr setAttr(LPCWSTR name, LPCWSTR val);

    protected:
        Document* m_pdoc;
        NODE m_id;
    };


Забесплатно получаем дешевую бинарную сериализацию.
_____________________
С уважением,
Stanislav V. Zudin
Re[2]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 12:31
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Здравствуйте, _hum_, Вы писали:


__>>Раньше на raw-ptr узел дерева, если говорить о двоичном варианте, выглядел


__>>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


SVZ>Предлагаю "ход конём". Заменить указатели на индексы в массиве.


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

SVZ>Забесплатно получаем дешевую бинарную сериализацию.


да, именно из-за нее вся возня со смартами (cereal не умеет выполнять сериализацию для raw-ptr — только для смартов)
Re: Реализация дерева средствами с++11
От: Pzz Россия https://github.com/alexpevzner
Дата: 16.04.16 12:43
Оценка:
Здравствуйте, _hum_, Вы писали:

__>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


Понятия не имею, как какие указатели в вашем волшебном языке называются, но по логике вещей, родитель владеет детьми, но не наоборот. Т.е., указатели "вниз" и "вверх" должны быть разными.
Re[2]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 12:48
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, _hum_, Вы писали:


__>>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


Pzz>Понятия не имею, как какие указатели в вашем волшебном языке называются, но по логике вещей, родитель владеет детьми, но не наоборот. Т.е., указатели "вниз" и "вверх" должны быть разными.


так точно. в этом и проблема.
Re[3]: Реализация дерева средствами с++11
От: Stanislav V. Zudin Россия  
Дата: 16.04.16 12:57
Оценка:
Здравствуйте, _hum_, Вы писали:

SVZ>>Предлагаю "ход конём". Заменить указатели на индексы в массиве.


__>ну, тогда ж придется писать аналог менеждера кучи (чтоб искал свободное место, куда можно вставлять новые элементы, чтобы помечал удаленные как свободные места и т.п.). но еще чуть-чуть, и я психану и все же наверное так и сделаю, потому что тратить столько времени на реализацию обычного дерева — это уж слишком (а я уже третий день с этим вожусь)


Ох уж эта молодёжь...

Вот получение узла из "менеджера кучи":

// ==========================================================================
// Создать узел
dom::NODE dom::Document::makeNode(LPCTSTR name)
{
    dom::NODE nodeN = m_NodeFreeList;
    if ( nodeN < 0 )
    {
        nodeN = static_cast<dom::NODE>(m_InfoNode.size());
        m_InfoNode.push_back( NodeInfo() );
    }
    else
    {
        m_NodeFreeList = m_InfoNode[nodeN].next;
        m_InfoNode[nodeN] = NodeInfo();
    }

    NAMEREF nref = makeNodeName(name);
    m_InfoNode[nodeN].name = nref;

    return nodeN;
}


Удаленные узлы помещаются в односвязный список, голова которого хранится в m_NodeFreeList.
Хранить можно и плоский список, и целые поддеревья (только в makeNode придется этот факт учитывать), в общем пространство для маневра обширное.

Свой код не привожу, потому что у меня там хитрое владение именами узлов — не думаю, что тебе это пригодится.

По сложности — задачка на пару часов для студента 2 курса.
_____________________
С уважением,
Stanislav V. Zudin
Re[3]: Реализация дерева средствами с++11
От: Pzz Россия https://github.com/alexpevzner
Дата: 16.04.16 12:58
Оценка:
Здравствуйте, _hum_, Вы писали:

Pzz>>Понятия не имею, как какие указатели в вашем волшебном языке называются, но по логике вещей, родитель владеет детьми, но не наоборот. Т.е., указатели "вниз" и "вверх" должны быть разными.


__>так точно. в этом и проблема.


Ну а почему бы не использовать для них разные типы?
Re: Реализация дерева средствами с++11
От: T4r4sB Россия  
Дата: 16.04.16 13:00
Оценка:
Здравствуйте, _hum_, Вы писали:

__>p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели


Ну если ты пишешь контейнер, в котором сам управляешь памятью, то таки придётся с ними повозиться.
Для дерева достаточно юников на потомков и сырого на родителя. Да, сырого на родителя. Да, если он не будет владеть и его время жизни меньше, чем у указуемого объекта, то можно и сырой, ничего не случится.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re: Реализация дерева средствами с++11
От: PM  
Дата: 16.04.16 13:11
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Раньше на raw-ptr узел дерева, если говорить о двоичном варианте, выглядел

__>
__>struct TNode
__>{
__>   TAtrributes m_Atrributes;

__>   TNode* m_pLeftChild;
__>   TNode* m_pRightChild;

__>   TNode* m_pParent;
__>};
__>



__>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


__>p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели


В N3840: A Proposal for the World’s Dumbest Smart Pointer, v3 описаны 3 варианта для таких случаев:

1) использовать как и раньше сырой указатель; постулировать, что сырые указатели не владеют памятью, на которую указывают

2) использовать [boost|std]::optional<TNode>

3) использовать std::unique_ptr<TNode> с do nothing deleter:
struct do_nothing
{
  template <class T>
  void operator ()(T*) { }; // do nothing
};
 
template <class T>
  using non_owning_ptr = unique_ptr<T, do_nothing>;
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 13:14
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Здравствуйте, _hum_, Вы писали:


SVZ>>>Предлагаю "ход конём". Заменить указатели на индексы в массиве.


__>>ну, тогда ж придется писать аналог менеждера кучи (чтоб искал свободное место, куда можно вставлять новые элементы, чтобы помечал удаленные как свободные места и т.п.). но еще чуть-чуть, и я психану и все же наверное так и сделаю, потому что тратить столько времени на реализацию обычного дерева — это уж слишком (а я уже третий день с этим вожусь)


SVZ>Ох уж эта молодёжь...


SVZ>Вот получение узла из "менеджера кучи":


  code
SVZ>
SVZ>// ==========================================================================
SVZ>// Создать узел
SVZ>dom::NODE dom::Document::makeNode(LPCTSTR name)
SVZ>{
SVZ>    dom::NODE nodeN = m_NodeFreeList;
SVZ>    if ( nodeN < 0 )
SVZ>    {
SVZ>        nodeN = static_cast<dom::NODE>(m_InfoNode.size());
SVZ>        m_InfoNode.push_back( NodeInfo() );
SVZ>    }
SVZ>    else
SVZ>    {
SVZ>        m_NodeFreeList = m_InfoNode[nodeN].next;
SVZ>        m_InfoNode[nodeN] = NodeInfo();
SVZ>    }

SVZ>    NAMEREF nref = makeNodeName(name);
SVZ>    m_InfoNode[nodeN].name = nref;

SVZ>    return nodeN;
SVZ>}
SVZ>

SVZ>Удаленные узлы помещаются в односвязный список, голова которого хранится в m_NodeFreeList.
SVZ>Хранить можно и плоский список, и целые поддеревья (только в makeNode придется этот факт учитывать), в общем пространство для маневра обширное.

SVZ>Свой код не привожу, потому что у меня там хитрое владение именами узлов — не думаю, что тебе это пригодится.


SVZ>По сложности — задачка на пару часов для студента 2 курса.


я уже все это писал раньше (я не молодежь), потому-то мне и лень было заново этим заниматься думал, с новым стандартом все это донельзя упростится — фигушки.
(и там же нюансы полезут с тем, что делать, если у сохраняемого типа нет конструктора по умолчанию — придется этими всеми списками инициализации и прочей мудатеньню заниматься.к тому же придется решать вопросы, которые больше всего не люблю — организационные — какое хранилище выбрать — статическое или динамически расширяемое, делать общий случай с темплейтами или конкретный, какие названия давать и т.п.). в общем, пока оставалась надежда выкрутиться малой кровью, но кажется, она на исходе
Re[2]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 13:16
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, _hum_, Вы писали:


__>>p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели


TB>Ну если ты пишешь контейнер, в котором сам управляешь памятью, то таки придётся с ними повозиться.

TB>Для дерева достаточно юников на потомков и сырого на родителя. Да, сырого на родителя. Да, если он не будет владеть и его время жизни меньше, чем у указуемого объекта, то можно и сырой, ничего не случится.

проблема возникла из : нужно организовать дерево, которое бы можно было сериализовать с помощью библиотеки cereal (она самая лекговесная и удобная из виденных мною). последняя умеет работать только с умными указателями.

и вы что признаете, что raw-ptr все-таки не всегда можно заменить смартами?
Re[3]: Реализация дерева средствами с++11
От: T4r4sB Россия  
Дата: 16.04.16 13:21
Оценка:
Здравствуйте, _hum_, Вы писали:

__>и вы что признаете, что raw-ptr все-таки не всегда можно заменить смартами?


Да, не везде.
Но это не значит, что можно руками фигачить new/delete
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re: Реализация дерева средствами с++11
От: -MyXa- Россия  
Дата: 16.04.16 13:22
Оценка:
Здравствуйте, _hum_, Вы писали:

__>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


Что конкретно за логика владения нарушается? Вроде, нормально работает.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[2]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 13:36
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>Здравствуйте, _hum_, Вы писали:


__>>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


MX>Что конкретно за логика владения нарушается? Вроде, нормально работает.


кто владелец-то? что делать с операторами присваивания и констркуторами копирования объектов, содержащих в себе в качестве данных такие деревья, и почему?
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 13:39
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, _hum_, Вы писали:


__>>и вы что признаете, что raw-ptr все-таки не всегда можно заменить смартами?


TB>Да, не везде.

TB>Но это не значит, что можно руками фигачить new/delete

кстати, оказывается, std::experimental::observer_ptr
Re[3]: Реализация дерева средствами с++11
От: -MyXa- Россия  
Дата: 16.04.16 13:46
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Здравствуйте, -MyXa-, Вы писали:


MX>>Здравствуйте, _hum_, Вы писали:


__>>>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


MX>>Что конкретно за логика владения нарушается? Вроде, нормально работает.


__>кто владелец-то?


Владелец чего именно?

__>что делать с операторами присваивания и констркуторами копирования объектов, содержащих в себе в качестве данных такие деревья, и почему?


А что бы ты делал при использовании голых указателей?
Если не поможет, будем действовать током... 600 Вольт (C)
Re[5]: Реализация дерева средствами с++11
От: -MyXa- Россия  
Дата: 16.04.16 13:50
Оценка:
Здравствуйте, _hum_, Вы писали:

__>кстати, оказывается, std::experimental::observer_ptr


На сколько мне известно, он ничего не делает. Это просто удобный способ отметить где у тебя, скорее всего, ошибка в программе.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 13:56
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>Здравствуйте, _hum_, Вы писали:


__>>Здравствуйте, -MyXa-, Вы писали:


MX>>>Здравствуйте, _hum_, Вы писали:


__>>>>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


MX>>>Что конкретно за логика владения нарушается? Вроде, нормально работает.


__>>кто владелец-то?


MX>Владелец чего именно?


владелец узлов дерева

__>>что делать с операторами присваивания и констркуторами копирования объектов, содержащих в себе в качестве данных такие деревья, и почему?


MX>А что бы ты делал при использовании голых указателей?


ясно что — делал бы клонирование (в противном бы случае удаление одного объекта привело бы к некорректной работе другого). в случае же с shared клонирование необязательно — два объекта могу работать через шареды с одним и теми же узлами.
Re[6]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 13:59
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>Здравствуйте, _hum_, Вы писали:


__>>кстати, оказывается, std::experimental::observer_ptr


MX>На сколько мне известно, он ничего не делает.



да, так и написано:

It is intended as a near drop-in replacement for raw pointer types, with the advantage that, as a vocabulary type, it indicates its intended use without need for detailed analysis by code readers.


MX> Это просто удобный способ отметить где у тебя, скорее всего, ошибка в программе.


?
Отредактировано 16.04.2016 14:01 _hum_ . Предыдущая версия .
Re[5]: Реализация дерева средствами с++11
От: -MyXa- Россия  
Дата: 16.04.16 14:08
Оценка:
Здравствуйте, _hum_, Вы писали:

__>ясно что — делал бы клонирование (в противном бы случае удаление одного объекта привело бы к некорректной работе другого). в случае же с shared клонирование необязательно — два объекта могу работать через шареды с одним и теми же узлами.


Так это-ж больше от задачи зависит. Надо клонировать — клонируй, не надо — не клонируй.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[7]: Реализация дерева средствами с++11
От: -MyXa- Россия  
Дата: 16.04.16 14:27
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Здравствуйте, -MyXa-, Вы писали:


MX>>Здравствуйте, _hum_, Вы писали:


__>>>кстати, оказывается, std::experimental::observer_ptr


MX>>На сколько мне известно, он ничего не делает.



__>да, так и написано:


__>

__>It is intended as a near drop-in replacement for raw pointer types, with the advantage that, as a vocabulary type, it indicates its intended use without need for detailed analysis by code readers.


Вот именно, что как reader, я сразу напрягусь и пойду искать — каким это таким незаконным способом ты этот указатель получил, и почему это observer_ptr гуляет по лесу один так далеко от того места, где его получили.

MX>> Это просто удобный способ отметить где у тебя, скорее всего, ошибка в программе.


__>?


Раньше у нас была куча легаси и голые указатели, теперь у нас везде observer_ptr, но программа падает ровно в тех же местах.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 14:53
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Здравствуйте, _hum_, Вы писали:


SVZ>>>Предлагаю "ход конём". Заменить указатели на индексы в массиве.


__>>ну, тогда ж придется писать аналог менеждера кучи (чтоб искал свободное место, куда можно вставлять новые элементы, чтобы помечал удаленные как свободные места и т.п.). но еще чуть-чуть, и я психану и все же наверное так и сделаю, потому что тратить столько времени на реализацию обычного дерева — это уж слишком (а я уже третий день с этим вожусь)


SVZ>Ох уж эта молодёжь...


SVZ>Вот получение узла из "менеджера кучи":


  code
SVZ>
SVZ>// ==========================================================================
SVZ>// Создать узел
SVZ>dom::NODE dom::Document::makeNode(LPCTSTR name)
SVZ>{
SVZ>    dom::NODE nodeN = m_NodeFreeList;
SVZ>    if ( nodeN < 0 )
SVZ>    {
SVZ>        nodeN = static_cast<dom::NODE>(m_InfoNode.size());
SVZ>        m_InfoNode.push_back( NodeInfo() );
SVZ>    }
SVZ>    else
SVZ>    {
SVZ>        m_NodeFreeList = m_InfoNode[nodeN].next;
SVZ>        m_InfoNode[nodeN] = NodeInfo();
SVZ>    }

SVZ>    NAMEREF nref = makeNodeName(name);
SVZ>    m_InfoNode[nodeN].name = nref;

SVZ>    return nodeN;
SVZ>}
SVZ>

SVZ>Удаленные узлы помещаются в односвязный список, голова которого хранится в m_NodeFreeList.
SVZ>Хранить можно и плоский список, и целые поддеревья (только в makeNode придется этот факт учитывать), в общем пространство для маневра обширное.

SVZ>Свой код не привожу, потому что у меня там хитрое владение именами узлов — не думаю, что тебе это пригодится.


SVZ>По сложности — задачка на пару часов для студента 2 курса.


кстати, в таком же варианте, если не заморачиваться, то придется сериализовывать и список свободных вершин, а значит, сериализация будет всегда давать максимально возможный объем, что не есть гуд.
Re[6]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 14:55
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>Здравствуйте, _hum_, Вы писали:


__>>ясно что — делал бы клонирование (в противном бы случае удаление одного объекта привело бы к некорректной работе другого). в случае же с shared клонирование необязательно — два объекта могу работать через шареды с одним и теми же узлами.


MX>Так это-ж больше от задачи зависит. Надо клонировать — клонируй, не надо — не клонируй.


это ходить по острию — если unique_ptr просто даст вам по рукам при попытке скопировать, то шаред, который изначально создавался под раздельное владение, просто проигнорирует, и ждите сюрпризов.
Re[8]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 14:59
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>Здравствуйте, _hum_, Вы писали:


__>>Здравствуйте, -MyXa-, Вы писали:


MX>>>Здравствуйте, _hum_, Вы писали:


__>>>>кстати, оказывается, std::experimental::observer_ptr


MX>>>На сколько мне известно, он ничего не делает.



__>>да, так и написано:


__>>

__>>It is intended as a near drop-in replacement for raw pointer types, with the advantage that, as a vocabulary type, it indicates its intended use without need for detailed analysis by code readers.


MX>Вот именно, что как reader, я сразу напрягусь и пойду искать — каким это таким незаконным способом ты этот указатель получил, и почему это observer_ptr гуляет по лесу один так далеко от того места, где его получили.


при чем тут незаконным? вам не надо ничего искать, вам сразу говорят, что он никем не владеет, и просто является средством доступа к объекту (еще бы добавили к нему возможность узнавать, существует ли объект, который ему дали при создании, или нет, и было бы вообще здорово).

MX>>> Это просто удобный способ отметить где у тебя, скорее всего, ошибка в программе.


__>>?


MX>Раньше у нас была куча легаси и голые указатели, теперь у нас везде observer_ptr, но программа падает ровно в тех же местах.


это только означает, что нет статистической связи между "ошибка в вашей программе" и "использование observer_ptr"
Re[7]: Реализация дерева средствами с++11
От: -MyXa- Россия  
Дата: 16.04.16 15:29
Оценка:
Здравствуйте, _hum_, Вы писали:

__>это ходить по острию — если unique_ptr просто даст вам по рукам при попытке скопировать, то шаред, который изначально создавался под раздельное владение, просто проигнорирует, и ждите сюрпризов.


Ну, какие проблемы? Сделай шареды деталью реализации, наружу выстави классы с нужной тебе семантикой.

А так-то да, везде свои трудности, голые указатели — голые, шареды — копируются, сборщик мусора..., впрочем, не будем об этом.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[5]: Реализация дерева средствами с++11
От: Stanislav V. Zudin Россия  
Дата: 16.04.16 16:04
Оценка:
Здравствуйте, _hum_, Вы писали:

__>кстати, в таком же варианте, если не заморачиваться, то придется сериализовывать и список свободных вершин, а значит, сериализация будет всегда давать максимально возможный объем, что не есть гуд.


Да, есть такое. Если у нас есть завязки на узлы дерева, то уплотнять всё дерево и перестраивать связи может быть муторно, особенно, если необходима поддержка отката.
Но с другой стороны, если это,скажем, редактор, то операций добавления всё же больше, чем удаления. Поэтому незадействованных узлов оказывается пренебрежимо мало.
_____________________
С уважением,
Stanislav V. Zudin
Re[8]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 16:51
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>Здравствуйте, _hum_, Вы писали:


__>>это ходить по острию — если unique_ptr просто даст вам по рукам при попытке скопировать, то шаред, который изначально создавался под раздельное владение, просто проигнорирует, и ждите сюрпризов.


MX>Ну, какие проблемы? Сделай шареды деталью реализации, наружу выстави классы с нужной тебе семантикой.



проблемы в том, что вы пытаетесь использовать только часть семантики shared_ptr/weak_ptr там, где по семантике должны стоять unique_ptr/observer_ptr (дерево обычно одно на объект, а не "разделяемое" между многими объектами)

MX>А так-то да, везде свои трудности, голые указатели — голые, шареды — копируются, сборщик мусора..., впрочем, не будем об этом.


просто чувствуется нехватка для unique_ptr полноценного напарника типа observer_ptr...
Re[6]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 16.04.16 16:55
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Здравствуйте, _hum_, Вы писали:


__>>кстати, в таком же варианте, если не заморачиваться, то придется сериализовывать и список свободных вершин, а значит, сериализация будет всегда давать максимально возможный объем, что не есть гуд.


SVZ>Да, есть такое. Если у нас есть завязки на узлы дерева, то уплотнять всё дерево и перестраивать связи может быть муторно, особенно, если необходима поддержка отката.

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

да, но если у кого-то залипнет клавиша вставки (или он просто побалуется), а потом он все лишнее удалит, то файл проекта будет огромный

п.с. пока остановился на варианте с функциями конвертации дерева из обычного в "на смартах (без parenta)"[для сериализации] и обратно
Re: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 07:09
Оценка:
Здравствуйте, _hum_, Вы писали:

__>p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели


Для начала тут интересно бы понять ответы на несколько вопросов.

1) Зачем вообще узлу владеть детьми? Почему узлу, а не дереву?
2) Если объекты как-то геморрно и сложно конструируются, то зачем им вообще лежать в узлах, а не в параллельном массиве, например, или по указателям или ещё как?

Например, если структуру ссылок в бинарном дереве хранить как-то так:
struct node_offsets {
    int parent_offset;
    enum { left_child_offset = 1 };
    int right_child_offset;
};


А хранить их в std::vector<struct node_offsets>, то
1) можно сразу написать методы
struct node_offsets {
    int parent_offset;
    enum { left_child_offset = 1 };
    int right_child_offset;
    
    node_offsets* get_patent() { return  get_by_offset( parent_offaset ); }
    node_offsets* get_left() { return  this + left_child_offset; }
    node_offsets* get_right() { return  get_by_offset( right_child_offset ); }
private:
    node_offsets* get_by_offset( int offset ) { return offset != 0 ? this + offset : 0; }    

};


2) А ещё можно по cur_node — &vector_of_nodes[0] сразу получить id узла,

3)а сам вектор можно заменить на контейнер, который сразу из файла буфер н память отображает и т. д...
А данные узлов можно вообще в параллельном векторе хранить, например
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 09:52
Оценка:
Здравствуйте, _hum_, Вы писали:

__>так точно. в этом и проблема.



А в чём проблема?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 10:46
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Здравствуйте, _hum_, Вы писали:


__>>проблема возникла из : нужно организовать дерево, которое бы можно было сериализовать с помощью библиотеки cereal (она самая лекговесная и удобная из виденных мною). последняя умеет работать только с умными указателями.


Ops>А если не сериализовывать этот указатель вообще? А после (или в процессе, смотря как оно сделано) десереализации обойти дерево и присвоить нужные значения.

Ops>Библиотеку не знаю, так что все умозрительно.

да, была такая идея, но остановило, что по сложности восстановление парентов не многим меньше, чем полностью конвертация дерева из обычного в "smart-based". а если учесть, что юниками намного сложнее манипулировать, все-таки решил остановиться на варианте дерева на полностью голых указателях с последующей конвертацией для сериализации.
Re[2]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 11:11
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели


E>Для начала тут интересно бы понять ответы на несколько вопросов.


E>1) Зачем вообще узлу владеть детьми? Почему узлу, а не дереву?


как мне видится, есть два взгляда на деррево:
1) как дерево поддеревьев, и тогда узел — это всегда корень поддерева (а значит, его существование неразрывно связано с существованием всех подузлов этого поддерева);
2) как набор узлов со специфической структурой (и тут владельцем узлов может быть уже кто-то другой).

и да, наверное мнен удобнее все-таки работать с вариантом 2), потому хорошо бы было все организовать на observer_ptr.

E>2) Если объекты как-то геморрно и сложно конструируются, то зачем им вообще лежать в узлах, а не в параллельном массиве, например, или по указателям или ещё как?


ну, тем самым вы усложняете структуру, откуда пойдет усложнение конструкторов копирования, операторов присваивания, деструкторов

E>Например, если структуру ссылок в бинарном дереве хранить как-то так:

  code
struct node_offsets {
E>    int parent_offset;
E>    enum { left_child_offset = 1 };
E>    int right_child_offset;
E>};


E>А хранить их в std::vector<struct node_offsets>, то

E>1) можно сразу написать методы
struct node_offsets {
E>    int parent_offset;
E>    enum { left_child_offset = 1 };
E>    int right_child_offset;
    
E>    node_offsets* get_patent() { return  get_by_offset( parent_offaset ); }
E>    node_offsets* get_left() { return  this + left_child_offset; }
E>    node_offsets* get_right() { return  get_by_offset( right_child_offset ); }
E>private:
E>    node_offsets* get_by_offset( int offset ) { return offset != 0 ? this + offset : 0; }    

E>};

E>2) А ещё можно по cur_node — &vector_of_nodes[0] сразу получить id узла,

E>3)а сам вектор можно заменить на контейнер, который сразу из файла буфер н память отображает и т. д...

E>А данные узлов можно вообще в параллельном векторе хранить, например

уже ж про это выше говорилось (см. обсуждение с Stanislav V. Z). вы просто забываете про редактирование (вставку, удаление).
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 11:14
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>так точно. в этом и проблема.



E>А в чём проблема?


в том, что с++ не дает возможности естественно отразить это различие ("указатели "вниз" и "вверх" должны быть разными") на языке смартов.
Re[3]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 11:33
Оценка:
Здравствуйте, _hum_, Вы писали:

__>1) как дерево поддеревьев, и тогда узел — это всегда корень поддерева (а значит, его существование неразрывно связано с существованием всех подузлов этого поддерева);

__>2) как набор узлов со специфической структурой (и тут владельцем узлов может быть уже кто-то другой).

IMHO, эти вопросы вообще не связаны. Например, можно поддержать GC для узлов, и вообще забить на владение внутри дерева...

__>и да, наверное мнен удобнее все-таки работать с вариантом 2), потому хорошо бы было все организовать на observer_ptr.

Это зависит от потребных операций. Для начала создавать/рушить эту структуру довольно долго...

__>ну, тем самым вы усложняете структуру, откуда пойдет усложнение конструкторов копирования, операторов присваивания, деструкторов

Каких деструкторов? В той структуре, которую я предложил, связи в дереве задаются POD-структурами, без конструкторов/деструкторов...

__>уже ж про это выше говорилось (см. обсуждение с Stanislav V. Z). вы просто забываете про редактирование (вставку, удаление).


А чем тут так сложна вставка/удаление?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 11:35
Оценка:
Здравствуйте, _hum_, Вы писали:

__>в том, что с++ не дает возможности естественно отразить это различие ("указатели "вниз" и "вверх" должны быть разными") на языке смартов.


IMHO, это не С++ не даёт, а твои установки или инструменты. Напримр юник_птр на детей, и простой на родителя, если дерево вообще нужно прошитое...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 11:37
Оценка:
Здравствуйте, _hum_, Вы писали:

__>да, была такая идея, но остановило, что по сложности восстановление парентов не многим меньше, чем полностью конвертация дерева из обычного в "smart-based". а если учесть, что юниками намного сложнее манипулировать, все-таки решил остановиться на варианте дерева на полностью голых указателях с последующей конвертацией для сериализации.


А зачем для сериализации куда-то конвертировать?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 11:59
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>1) как дерево поддеревьев, и тогда узел — это всегда корень поддерева (а значит, его существование неразрывно связано с существованием всех подузлов этого поддерева);

__>>2) как набор узлов со специфической структурой (и тут владельцем узлов может быть уже кто-то другой).

E>IMHO, эти вопросы вообще не связаны. Например, можно поддержать GC для узлов, и вообще забить на владение внутри дерева...


конечно, можно делать все, как хочешь. речь же шла о наиболее естественном (для задачи) представлении.

__>>и да, наверное мнен удобнее все-таки работать с вариантом 2), потому хорошо бы было все организовать на observer_ptr.

E>Это зависит от потребных операций. Для начала создавать/рушить эту структуру довольно долго...

для двоичного не дольше O(N) — N -число узлов

__>>ну, тем самым вы усложняете структуру, откуда пойдет усложнение конструкторов копирования, операторов присваивания, деструкторов

E>Каких деструкторов? В той структуре, которую я предложил, связи в дереве задаются POD-структурами, без конструкторов/деструкторов...

вы же предложили объекты (атрибуты узла) держать отдельно, делая на них ссылки. вот те объекты нужно будет как-то удалять при разрушении дерева и копировать при создании копии.

__>>уже ж про это выше говорилось (см. обсуждение с Stanislav V. Z). вы просто забываете про редактирование (вставку, удаление).


E>А чем тут так сложна вставка/удаление?


при том, что у вас при этом начнут образовываться дырки в массиве, которые нужно будет отслеживать и заполнять, а это уже отдельная задача.
Re[6]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 12:02
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>в том, что с++ не дает возможности естественно отразить это различие ("указатели "вниз" и "вверх" должны быть разными") на языке смартов.


E>IMHO, это не С++ не даёт, а твои установки или инструменты. Напримр юник_птр на детей, и простой на родителя, если дерево вообще нужно прошитое...


Erop, я же несколько раз повторил, что проблема — как все перевести на язык смартов ил признать, что смарты не смогут во всем заменить простые указатели.
Re[6]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 12:03
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>да, была такая идея, но остановило, что по сложности восстановление парентов не многим меньше, чем полностью конвертация дерева из обычного в "smart-based". а если учесть, что юниками намного сложнее манипулировать, все-таки решил остановиться на варианте дерева на полностью голых указателях с последующей конвертацией для сериализации.


E>А зачем для сериализации куда-то конвертировать?


затем, что библиотека сериализации cereal, которой я пользуюсь (да наверное и остальные)работает только с stl-овскими объектами, в частности, только с умными указателями.
Re[5]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 12:12
Оценка:
Здравствуйте, _hum_, Вы писали:

__>конечно, можно делать все, как хочешь. речь же шла о наиболее естественном (для задачи) представлении.

Ну я с того и начал, что хорошобы ответить на ряд вопросов "зачем?"... :shuffle

__>для двоичного не дольше O(N) — N -число узлов

Если структуру дерева хранить в std::vector, то рушить — O(1)

__>вы же предложили объекты (атрибуты узла) держать отдельно, делая на них ссылки. вот те объекты нужно будет как-то удалять при разрушении дерева и копировать при создании копии.


А когда будет не надо?
Ну и потом, данные узла тоже могут быть POD...

__>при том, что у вас при этом начнут образовываться дырки в массиве, которые нужно будет отслеживать и заполнять, а это уже отдельная задача.

Она довольно простая и легко переиспользуется...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 12:12
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Erop, я же несколько раз повторил, что проблема — как все перевести на язык смартов ил признать, что смарты не смогут во всем заменить простые указатели.


IMHO, очевидно, что не могут...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 12:14
Оценка:
Здравствуйте, _hum_, Вы писали:

__>затем, что библиотека сериализации cereal, которой я пользуюсь (да наверное и остальные)работает только с stl-овскими объектами, в частности, только с умными указателями.


1) Ну так это ограничение этой библиотеки же, а не языка?
2) Я не пользуюсь, поэтому не знаю. А нельзя, структуру сериализовывать самому, а данные библиотекой?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 12:28
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>конечно, можно делать все, как хочешь. речь же шла о наиболее естественном (для задачи) представлении.

E>Ну я с того и начал, что хорошобы ответить на ряд вопросов "зачем?"... :shuffle

для графического задания flow-chart-а алгоритма

__>>для двоичного не дольше O(N) — N -число узлов

E>Если структуру дерева хранить в std::vector, то рушить — O(1)

если не считать еще и разрушение менеджера хранения (с его списком свободных вершин)

__>>вы же предложили объекты (атрибуты узла) держать отдельно, делая на них ссылки. вот те объекты нужно будет как-то удалять при разрушении дерева и копировать при создании копии.


E>А когда будет не надо?


?

E>Ну и потом, данные узла тоже могут быть POD...


а могут и не быть. да и вообще дополнительна индирекция — это дополнительная головная боль (отслеживание синхронизации, усложнение копирования и т.п.)

__>>при том, что у вас при этом начнут образовываться дырки в массиве, которые нужно будет отслеживать и заполнять, а это уже отдельная задача.

E>Она довольно простая и легко переиспользуется...

"дьявол в деталях"

расскажите как вы видите это "просто и легко" (только желательно сперва прочитав наше обсуждение со Stanislav V. Z.)


__>>Erop, я же несколько раз повторил, что проблема — как все перевести на язык смартов ил признать, что смарты не смогут во всем заменить простые указатели.


E>IMHO, очевидно, что не могут...


откуда очевидно-то?

__>>затем, что библиотека сериализации cereal, которой я пользуюсь (да наверное и остальные)работает только с stl-овскими объектами, в частности, только с умными указателями.


E>1) Ну так это ограничение этой библиотеки же, а не языка?


языка, потому что библиотека заточена под новый стандарт

E>2) Я не пользуюсь, поэтому не знаю.


да что там знать она просто гарантирует автоматическую сериализацию любого типа stl

E>А нельзя, структуру сериализовывать самому, а данные библиотекой?


самое сложное — это именно сериализация структуры дерева
Re[7]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 13:00
Оценка:
Здравствуйте, _hum_, Вы писали:

__>>>конечно, можно делать все, как хочешь. речь же шла о наиболее естественном (для задачи) представлении.

E>>Ну я с того и начал, что хорошобы ответить на ряд вопросов "зачем?"... :shuffle

__>для графического задания flow-chart-а алгоритма


Это не ответы на вопросы "зачем"...
Чем плохо для этой графической вьюшки, все объекты отдать во владение дереву?
Ненужные узлы можно просто "терять", оставляя их во владении дерева.
При сериализации и копировании можно писать/копировать только дерево, что заменит GC...

__>если не считать еще и разрушение менеджера хранения (с его списком свободных вершин)

Оно будет вообще бесплатным...

E>>А когда будет не надо?


__>?


Ну мы рассматриваем несколько альтернатив же? В какой их них данные узлов не надо будет рушить?

__>а могут и не быть. да и вообще дополнительна индирекция — это дополнительная головная боль (отслеживание синхронизации, усложнение копирования и т.п.)


А ты делай копирование через интерфейс/абстракции дерева, и не будешь зависеть от реализации

__>"дьявол в деталях"


Там всё очень просто.
Например, если данные о структуре — пара int'ов, как я предлагал, то в одном хранишь число пустых ячеек в блоке, а в другом -- смещение не начало след. блока.

__>расскажите как вы видите это "просто и легко" (только желательно сперва прочитав наше обсуждение со Stanislav V. Z.)


E>>IMHO, очевидно, что не могут...


__>откуда очевидно-то?


Ну много откуда... Умные указатели автоматизируют управление владением и совместным использованием, но сфера применения указателей шире .
В любом случае INHO означает, что МНЕ, очевидно, и это так...

__>языка, потому что библиотека заточена под новый стандарт

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

__>да что там знать она просто гарантирует автоматическую сериализацию любого типа stl

Как видишь, не любого...

__>самое сложное — это именно сериализация структуры дерева

Выносишь её в std::vector< node_offsets > и получаь сериализацию автоматом...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 16:18
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>>>конечно, можно делать все, как хочешь. речь же шла о наиболее естественном (для задачи) представлении.

E>>>Ну я с того и начал, что хорошобы ответить на ряд вопросов "зачем?"... :shuffle

__>>для графического задания flow-chart-а алгоритма


E>Это не ответы на вопросы "зачем"...

E>Чем плохо для этой графической вьюшки, все объекты отдать во владение дереву?
E>Ненужные узлы можно просто "терять", оставляя их во владении дерева.
E>При сериализации и копировании можно писать/копировать только дерево, что заменит GC...

я потерял нить беседы. по-моему, я о том же и говорил, что мне удобнее, чтобы владельцем были не узлы, а сам объект, содержащий дерево.

__>>если не считать еще и разрушение менеджера хранения (с его списком свободных вершин)

E>Оно будет вообще бесплатным...

бесплатным ничего не бывает. значит, объем у вас вырастет

E>>>А когда будет не надо?


__>>?


E>Ну мы рассматриваем несколько альтернатив же? В какой их них данные узлов не надо будет рушить?


всегда надо будет

__>>а могут и не быть. да и вообще дополнительна индирекция — это дополнительная головная боль (отслеживание синхронизации, усложнение копирования и т.п.)


E>А ты делай копирование через интерфейс/абстракции дерева, и не будешь зависеть от реализации




__>>"дьявол в деталях"


E>Там всё очень просто.

E>Например, если данные о структуре — пара int'ов, как я предлагал, то в одном хранишь число пустых ячеек в блоке, а в другом -- смещение не начало след. блока.

ну, получается связный список, который, если хранить в том же массиве, что и дерево, даст вам при сериализации разрастание сериализованных данных


__>>языка, потому что библиотека заточена под новый стандарт

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



__>>да что там знать она просто гарантирует автоматическую сериализацию любого типа stl

E>Как видишь, не любого...

любого. raw-ptr не входит в stl.

__>>самое сложное — это именно сериализация структуры дерева

E>Выносишь её в std::vector< node_offsets > и получаь сериализацию автоматом...

вместе со связным списком свободных блоков, а значит, дополнительным объемом
Re[9]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 16:58
Оценка:
Здравствуйте, _hum_, Вы писали:

__>я потерял нить беседы. по-моему, я о том же и говорил, что мне удобнее, чтобы владельцем были не узлы, а сам объект, содержащий дерево.


Да, я тоже думаю, что это было бы удобнее, и юник-птры тут не нужны...

__>всегда надо будет

Тогда по этому параметру все схемы равны

__>ну, получается связный список, который, если хранить в том же массиве, что и дерево, даст вам при сериализации разрастание сериализованных данных


Ну, например, можно время от времени запускать GCкомпактификацию...

__>любого. raw-ptr не входит в stl.

Ну не важно...

__>вместе со связным списком свободных блоков, а значит, дополнительным объемом


И что с того? Это проблема? Обычно RAM дороже же диска?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 20:11
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>ну, получается связный список, который, если хранить в том же массиве, что и дерево, даст вам при сериализации разрастание сериализованных данных


E>Ну, например, можно время от времени запускать GCкомпактификацию...


вввооот. а это уже лишнее время, лишний код...

__>>любого. raw-ptr не входит в stl.

E>Ну не важно...

важно, если речь про поддержку объектов сериализации

__>>вместе со связным списком свободных блоков, а значит, дополнительным объемом


E>И что с того? Это проблема? Обычно RAM дороже же диска?


проблема, что файл проекта станет большим, по почте не переслать, например.
Re[11]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 17.04.16 20:53
Оценка:
Здравствуйте, _hum_, Вы писали:

__>вввооот. а это уже лишнее время, лишний код...

Лишний по сравнению с чем?

Можно просто копировать дерево обходом, например... Это же в любом случае нужно будет написать?

__>проблема, что файл проекта станет большим, по почте не переслать, например.

Ну, можно перед записью итерировать пустое место, и если оно большое -- компактифицировать, заменяя дерево на копию, созданную обходом дерева.

Ну, грубо говоря, пусть у нас дерево хранят в двух параллельных структурах — вектор из смещений + вектор из юник_птров на данные узлов, ну и индекса входа в список пустых.

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

Ну и тривиально сериализуем...

Я к тому, что возможны разные подход, стоит выбирать дизайн осознанно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[12]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 17.04.16 21:48
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>вввооот. а это уже лишнее время, лишний код...

E>Лишний по сравнению с чем?

лишний по сравнению с изначальной задачей — создать сериализуемое дерево

E>Можно просто копировать дерево обходом, например... Это же в любом случае нужно будет написать?


в какой момент?

__>>проблема, что файл проекта станет большим, по почте не переслать, например.

E>Ну, можно перед записью итерировать пустое место, и если оно большое -- компактифицировать, заменяя дерево на копию, созданную обходом дерева.

E>Ну, грубо говоря, пусть у нас дерево хранят в двух параллельных структурах — вектор из смещений + вектор из юник_птров на данные узлов, ну и индекса входа в список пустых.


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


E>Ну и тривиально сериализуем...


E>Я к тому, что возможны разные подход, стоит выбирать дизайн осознанно...


спасибо, но мне всего лишь нужно было организовать обычное сериализуемое дерево, а тут получается я еще буду тратить уйму времени на написание и отладку всех этих компактификаторов, менеждеров и прочую лабуду. я же изначально и поднял эту проблему — думал, что с приходом с++11 все значительно упростилось. ан нет. оказывается, ничего подобного.
Re[13]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 18.04.16 04:14
Оценка:
Здравствуйте, _hum_, Вы писали:

__>лишний по сравнению с изначальной задачей — создать сериализуемое дерево

Ну конструктор копии у дерева предполагался? Компактификатор — это конструктор копии, написанный через итерацию дерева...

__>в какой момент?

Ну, если парит именно размер файла, то перед записью смотреть, как много есть свободных блоков. Если слишком много, то компактифицировать.
Можно завести счётчик числа свободных блоков, и при освобождении блоков (пополнении списка пустых) его увеличивать, а при аллокации уменьшать, и если пустых слишком много, то и компактифицировать...

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


Компактификатор — это просто конструктор глубокой копии. Менеджер -- просто список на маркерах.
Что там писать?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[14]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 18.04.16 07:41
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>лишний по сравнению с изначальной задачей — создать сериализуемое дерево

E>Ну конструктор копии у дерева предполагался? Компактификатор — это конструктор копии, написанный через итерацию дерева...

ну это же обман. конструктор копии на то и конструктор копии, чтобы давать КОПИЮ (КЛОН), а не "компактифицированный вариант"


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


E>Компактификатор — это просто конструктор глубокой копии. Менеджер -- просто список на маркерах.

E>Что там писать?

ну да, по мелочевке кажется ерунда, но этой мелочевки набирается очень много, и каждая требует учета и отладки.
Re: Реализация дерева средствами с++11
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 18.04.16 07:44
Оценка:
Здравствуйте, _hum_, Вы писали:

__>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?

Используй raw pointer для родителя. С другой стороны вопрос, зачем тебе нужен указатель на родителя?
__>p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели
Они не устарели, просто с ними надо быть очень внимательным и понимать где, когда и зачем будет использоваться код, учитывать появления исключений и многопоточность.
Sic luceat lux!
Re[15]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 18.04.16 07:46
Оценка:
Здравствуйте, _hum_, Вы писали:

__>>>лишний по сравнению с изначальной задачей — создать сериализуемое дерево

E>>Ну конструктор копии у дерева предполагался? Компактификатор — это конструктор копии, написанный через итерацию дерева...

__>ну это же обман. конструктор копии на то и конструктор копии, чтобы давать КОПИЮ (КЛОН), а не "компактифицированный вариант"


Почему обман? Код, который так бы ты поместил в конструктор копии, поместишь в компактификатор, а конструктор копии, как и сериализатор, будут тривиальными...

__>ну да, по мелочевке кажется ерунда, но этой мелочевки набирается очень много, и каждая требует учета и отладки.


По идее код глубокого копирования обходом дерева в любой реализации будет, тут экономии не выйдет. Просто в одной он будет помещён в компактификатор, а в другой в конструктор копии.
Так что получаем размен конвертилки видов дерева, как у тебя, что гарантирует перерасход памяти в 100%, против тупейшего менеджера блоков...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[16]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 18.04.16 08:03
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>>>лишний по сравнению с изначальной задачей — создать сериализуемое дерево

E>>>Ну конструктор копии у дерева предполагался? Компактификатор — это конструктор копии, написанный через итерацию дерева...

__>>ну это же обман. конструктор копии на то и конструктор копии, чтобы давать КОПИЮ (КЛОН), а не "компактифицированный вариант"


аа, вы наверное имели в виду, что нынешний мой конструктор копии — это в вашем варианте компактификатор. тогда понятно.

E>Почему обман? Код, который так бы ты поместил в конструктор копии, поместишь в компактификатор, а конструктор копии, как и сериализатор, будут тривиальными...


__>>ну да, по мелочевке кажется ерунда, но этой мелочевки набирается очень много, и каждая требует учета и отладки.


E>По идее код глубокого копирования обходом дерева в любой реализации будет, тут экономии не выйдет. Просто в одной он будет помещён в компактификатор, а в другой в конструктор копии.

E>Так что получаем размен конвертилки видов дерева, как у тебя, что гарантирует перерасход памяти в 100%, против тупейшего менеджера блоков...

выделенное не понял — какой перерасход памяти?
Re[2]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 18.04.16 08:05
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Здравствуйте, _hum_, Вы писали:


__>>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?

K>Используй raw pointer для родителя. С другой стороны вопрос, зачем тебе нужен указатель на родителя?

ясно же, зачем, чтобы иметь возможность выполнения быстрой вставки, например.

__>>p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели

K>Они не устарели, просто с ними надо быть очень внимательным и понимать где, когда и зачем будет использоваться код, учитывать появления исключений и многопоточность.

в том смысле, что в "будущем ими пользоваться практически не будут, и все заменят умные"
Re[17]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 18.04.16 08:12
Оценка:
Здравствуйте, _hum_, Вы писали:

__>выделенное не понял — какой перерасход памяти?


Ну я так понял, что ты под сериализацию строишь другое дерево? Или что ты делаешь вместо прошивания дерева руками после загрузки?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[19]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 18.04.16 08:32
Оценка:
Здравствуйте, _hum_, Вы писали:

__>аа, ну так озу нас не волнует

Ну, тогда, можно компактифицировать перед записью дерево с любым непустым списком свободных блоков... Это явно не дороже создания копии с другой структурой
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 18.04.16 08:34
Оценка:
Здравствуйте, _hum_, Вы писали:

__>ясно же, зачем, чтобы иметь возможность выполнения быстрой вставки, например.

Что такое "быстрая вставка" в бинарное дерево?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Реализация дерева средствами с++11
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 18.04.16 09:38
Оценка:
Здравствуйте, _hum_, Вы писали:

__>ясно же, зачем, чтобы иметь возможность выполнения быстрой вставки, например.

Что такое "быстрая вставка" в дереве? Любая вставка в дерево начинается с поиска.
__>в том смысле, что в "будущем ими пользоваться практически не будут, и все заменят умные"
Ну ерунда же.
Sic luceat lux!
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 18.04.16 10:26
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>ясно же, зачем, чтобы иметь возможность выполнения быстрой вставки, например.

E>Что такое "быстрая вставка" в бинарное дерево?

insert(TNode* pNodeWhere) за O(1)
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 18.04.16 10:27
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Здравствуйте, _hum_, Вы писали:


__>>ясно же, зачем, чтобы иметь возможность выполнения быстрой вставки, например.

K>Что такое "быстрая вставка" в дереве? Любая вставка в дерево начинается с поиска.

insert(TNode* pNodeWhere) за O(1)

__>>в том смысле, что в "будущем ими пользоваться практически не будут, и все заменят умные"

K>Ну ерунда же.

"ваши доказательства" (с)
Re[5]: Реализация дерева средствами с++11
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 18.04.16 10:41
Оценка:
Здравствуйте, _hum_, Вы писали:

__>>>ясно же, зачем, чтобы иметь возможность выполнения быстрой вставки, например.

K>>Что такое "быстрая вставка" в дереве? Любая вставка в дерево начинается с поиска.
__>insert(TNode* pNodeWhere) за O(1)
И куда ты это вставишь? Мне кажется есть только одн оместо для этого .
__>>>в том смысле, что в "будущем ими пользоваться практически не будут, и все заменят умные"
K>>Ну ерунда же.
__>"ваши доказательства" (с)
Совместимость с С.
Sic luceat lux!
Re[2]: Реализация дерева средствами с++11
От: BulatZiganshin  
Дата: 18.04.16 11:46
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Если делать по-человечески, то все узлы дерева должны использовать общий счётчик ссылок: пока есть хоть один указатель на хоть один узел дерева, всё дерево остаётся живым.


... и далее следует небольшой комментарий к утверждению "благодаря shared_ptr, C++ стало так же удобно пользоваться, как языками с GC"
Люди, я люблю вас! Будьте бдительны!!!
Re[5]: Реализация дерева средствами с++11
От: Erop Россия  
Дата: 18.04.16 11:52
Оценка:
Здравствуйте, _hum_, Вы писали:

__>>>ясно же, зачем, чтобы иметь возможность выполнения быстрой вставки, например.

E>>Что такое "быстрая вставка" в бинарное дерево?

__>insert(TNode* pNodeWhere) за O(1)



ничего не понял.
1) TNode* -- это типа итератор узлов да? Что мешает хранить в нём указатель на отца тоже?
2) Дерево, как я понял, бинарное? То есть у любого узла, не являющегося листом, два сына.

Вот у нас есть узел node, у неге дети left, right, я хочу туда вставить узел toAdd, кто кого в результате усыновит?
В бинарном дереве просто так узел не добавишь, так как узлов всегда на 1 меньше, чем листьев. Так что надо всегда добавлять лист, узел, и что-то перестраивать, например перебалансировывать...
Ну это если дерево не за один проход строится, а инкрементально...

Ну, то есть в прошитых деревьях нет ничего странного, но про них тоже стоит выяснить, оно точно надо, или это лишнее усложенение дизайна...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: Реализация дерева средствами с++11
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 18.04.16 11:55
Оценка:
Здравствуйте, _hum_, Вы писали:

K>>>>Что такое "быстрая вставка" в дереве? Любая вставка в дерево начинается с поиска.

__>>>insert(TNode* pNodeWhere) за O(1)
K>>И куда ты это вставишь? Мне кажется есть только одн оместо для этого .
__>список — частный случай дерева, но ставка там не в одно место: std::list::insert
Одна история ох...ее другой. Ладно, проехали.
Sic luceat lux!
Re[3]: Реализация дерева средствами с++11
От: Кодт Россия  
Дата: 18.04.16 12:24
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>... и далее следует небольшой комментарий к утверждению "благодаря shared_ptr, C++ стало так же удобно пользоваться, как языками с GC"


У языков с GC нет причин для того, чтобы различать составной объект (которым является всё дерево) и его мелкие детали (узлы). Мусороуборщик сам разберётся.
Но вообще, это архитектурное искушение.
Которое выстреливает, например, если один поток (или одна сопрограмма, или один уровень вызова) занимается забегом по дереву, а второй в это время отчекрыживает ветку.

Так что органические ограничения shared_ptr немножко дисциплинируют.

А если эти ограничения реально мешают, то придётся так или иначе отказываться от shared_ptr — включая использование собственных (велосипедных или нормальных) мусороуборщиков.
Перекуём баги на фичи!
Re[6]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 18.04.16 12:52
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>>>ясно же, зачем, чтобы иметь возможность выполнения быстрой вставки, например.

E>>>Что такое "быстрая вставка" в бинарное дерево?

__>>insert(TNode* pNodeWhere) за O(1)



E>ничего не понял.

E>1) TNode* -- это типа итератор узлов да? Что мешает хранить в нём указатель на отца тоже?

не итератор, а указатель на узел. получен он может быть, например, из графического представления узла (каждый графический элемент, представляющий блок, будет содержать указатель на узел, который он представляет) [напоминаю, речь о графическом представлении flow-chart-а]


E>2) Дерево, как я понял, бинарное? То есть у любого узла, не являющегося листом, два сына.


не два сына (речь не о полном дереве), а не более двух и специфическое

Re[7]: Реализация дерева средствами с++11
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 18.04.16 15:02
Оценка:
Здравствуйте, _hum_, Вы писали:

__>не два сына (речь не о полном дереве), а не более двух и специфическое

R-дерево?
Sic luceat lux!
Re[8]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 18.04.16 18:56
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Здравствуйте, _hum_, Вы писали:


__>>не два сына (речь не о полном дереве), а не более двух и специфическое

K>R-дерево?

с чего вы взяли?
Re[2]: Реализация дерева средствами с++11
От: T4r4sB Россия  
Дата: 19.04.16 08:59
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Если делать по-человечески, то все узлы дерева должны использовать общий счётчик ссылок: пока есть хоть один указатель на хоть один узел дерева, всё дерево остаётся живым.


Почему?
Это нужно далеко не во всех задачах.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re: Реализация дерева средствами с++11
От: Mr.Delphist  
Дата: 19.04.16 10:54
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Раньше на raw-ptr узел дерева, если говорить о двоичном варианте, выглядел

__>
__>struct TNode
__>{
__>   TAtrributes m_Atrributes;

__>   TNode* m_pLeftChild;
__>   TNode* m_pRightChild;

__>   TNode* m_pParent;
__>};
__>



__>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


__>p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели


Бустовые shared_ptr + weak_ptr должны спасти отца русской демократии. Надо лишь для себя определиться с семантикой, кто будет владеть shared-указателем на кого (родитель на дочерних или дочерние на родителя), тогда weak должен будет использоваться в обратном направлении. Оба варианта имеют право на жизнь, в зависимости от предполагаемых сценариев.
Re[4]: Реализация дерева средствами с++11
От: T4r4sB Россия  
Дата: 19.04.16 10:59
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Если дерево извне представлено цельным объектом, то должны быть владеющие указатели на дерево (не на корневой узел, а именно на дерево, распоряжающееся корневым узлом и всеми прочими узлами) и голые указатели/итераторы на узлы. Которые инвалидируются, если соответствующие узлы умерли (или даже если они перемещены каким-то внезапным способом — тут уже всё зависит от контракта итератора).


Сложновато как-то, в СТЛ сколько деревьев, и ни одно из них не отвечает за итераторы, ссылающиеся на узлы. Выходит из зоны видимости — и сразу дохнет со всеми узлами.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[5]: Реализация дерева средствами с++11
От: Кодт Россия  
Дата: 19.04.16 11:09
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, Кодт, Вы писали:


К>>Если дерево извне представлено цельным объектом, то должны быть владеющие указатели на дерево (не на корневой узел, а именно на дерево, распоряжающееся корневым узлом и всеми прочими узлами) и голые указатели/итераторы на узлы. Которые инвалидируются, если соответствующие узлы умерли (или даже если они перемещены каким-то внезапным способом — тут уже всё зависит от контракта итератора).


TB>Сложновато как-то, в СТЛ сколько деревьев, и ни одно из них не отвечает за итераторы, ссылающиеся на узлы. Выходит из зоны видимости — и сразу дохнет со всеми узлами.


Как раз ничего сложного. Именно это я и сказал: дерево — объект, узлы — детали реализации, итераторы — сами себе злые буратины.
Хочешь распределённо владеть деревом — делай shared_ptr на дерево.
Перекуём баги на фичи!
Re[2]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 19.04.16 11:26
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>Здравствуйте, _hum_, Вы писали:


__>>Раньше на raw-ptr узел дерева, если говорить о двоичном варианте, выглядел

__>>
__>>struct TNode
__>>{
__>>   TAtrributes m_Atrributes;

__>>   TNode* m_pLeftChild;
__>>   TNode* m_pRightChild;

__>>   TNode* m_pParent;
__>>};
__>>



__>>При попытке перевести все на язык смартов возникают трудности: если делать на unique_ptr (что достаточно логично), то непонятно, как быть с указателем на родителя. Если же делать на shared_ptr / weak_ptr, то нарушается логика владения. Как в таком случае быть?


__>>p.s. T4r4sB, это же вы, по-моему, недавно говорили, что raw-ptr устарели


MD>Бустовые shared_ptr + weak_ptr должны спасти отца русской демократии. Надо лишь для себя определиться с семантикой, кто будет владеть shared-указателем на кого (родитель на дочерних или дочерние на родителя), тогда weak должен будет использоваться в обратном направлении. Оба варианта имеют право на жизнь, в зависимости от предполагаемых сценариев.


а что в бусте семантика shared_ptr + weak_ptr отлична от семантики stl-ксих аналогов?
Re[3]: Реализация дерева средствами с++11
От: Mr.Delphist  
Дата: 19.04.16 11:44
Оценка:
Здравствуйте, _hum_, Вы писали:

__>а что в бусте семантика shared_ptr + weak_ptr отлична от семантики stl-ксих аналогов?


Это они самые и есть.
Re[4]: Реализация дерева средствами с++11
От: _hum_ Беларусь  
Дата: 19.04.16 12:01
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>Здравствуйте, _hum_, Вы писали:


__>>а что в бусте семантика shared_ptr + weak_ptr отлична от семантики stl-ксих аналогов?


MD>Это они самые и есть.


тогда уже обсуждалось выше с -MyXa- от 16.04.16 16:22
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.