Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> поиск элемента одного дерева в другом. 
:(
    Опции темы
tonchitos
Дата 18.3.2008, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 447
Регистрация: 24.2.2007

Репутация: нет
Всего: 40



у меня два дерева. Одно дерево как структура данных, другое как графическая(treectrl). Деревья одинаковы, те имеют одинаковую структуру и имена. В одном дереве выбран какой-то потомок.

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


мое дерево
Код


namespace GUI
{

    class Node 
    {public:
        std::vector<Node> childs;
        std::string Name;
        int pole1;
        int pole2;
        int level;
        int size;
        
    public:

    Node();

    Node (const Node &obj)
    {
        childs = obj.childs;
        Name = obj.Name;
    }

    void LoadData(std::string str)
    {
        Name=str;
    }
    
    int GetNumChilds ()
    {
        return childs.size();
    }

    const Node & GetChild (int pos) const
    {
        return childs[pos];
    }

    Node & GetChild (int pos)
    {
        return childs[pos];
    }

    std::ostream& printFile(std::ostream& stream, unsigned int tab) const;
    std::istream& readFile (std::istream &stream);
    bool insertChild (int pos, Node & element );
    bool removeChild (int pos);    
    Node & operator = (const Node & from);

    ~Node();

    };
}


що делать.


--------------------
– Люди забыли эту истину, – сказал Лис, – но ты не забывай: ты навсегда в ответе за всех, кого приручил.
PM MAIL   Вверх
Alek86
Дата 18.3.2008, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



спецально для таких вопросов создана ветка для новичков


--------------------
user posted image    user posted image
PM MAIL   Вверх
tonchitos
Дата 18.3.2008, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 447
Регистрация: 24.2.2007

Репутация: нет
Всего: 40



вот я примерно так сделала:
Код


void TreeDlg::treeAssosiation(std::vector<GUI::Node>::iterator i, 
                              std::vector<GUI::Node>::iterator end, 
                              int itemLevel)
{
    for(int j=0; j < itemLevel - i->level; j++)
        Itm = m_tree.GetParentItem((Itm);

    for(;i != end; ++i)
    {    

        if((i->Name.c_str()==m_tree.GetItemText(Itm))&&(lev==level));
            //элемент найден
        else
            if (i->Name.c_str()==m_tree.GetItemText(Itm))
                return treeAssosiation(i->childs.begin(), i->childs.end(), itemLevel)
            else
                continue;
    }
}


не красиво?


--------------------
– Люди забыли эту истину, – сказал Лис, – но ты не забывай: ты навсегда в ответе за всех, кого приручил.
PM MAIL   Вверх
bsa
Дата 18.3.2008, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



вообще-то это не очень верно. На одном уровне могут быть разные имена, но у разных веток:
Код
   node1
  /     \
node2   node3
 /  \    /  \
n1 n2   n1  n3
Уровень одинаковый, имена одинаковые, а ветки разные.
Искать нужно опять рекурсивно. Для этого сначала нужно собрать все имена нодов от текущего до корня (дерева в диалоге). А потом, последовательно выбирать нужные имена в другом дереве.

Кстати, тебе не надоело везде писать std::vector<Node>?.. Может стоит сделать typedef std::vector<Node> Nodes?  smile 
PM   Вверх
tonchitos
Дата 18.3.2008, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 447
Регистрация: 24.2.2007

Репутация: нет
Всего: 40



bsa, спасибо. Я предпологала отсутствие совпадений у одного родителя
типа нельзя так:

        рут
нод1   нод1

typedef std сделать надо, но тогда все то исправлять....

Или не полениться, тк нехороший тон?




--------------------
– Люди забыли эту истину, – сказал Лис, – но ты не забывай: ты навсегда в ответе за всех, кого приручил.
PM MAIL   Вверх
bsa
Дата 18.3.2008, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Вот скажи, тебе не лень писать std::vector<Node> каждый раз? А если потом выяснится, что вместо vector надо использовать map или list? Что делать будешь?
Имхо, делать typedef - это не правило хорошего тона, это просто правило. Потому что рано или поздно могут возникнуть следующие вещи: std::vector< std::list< std::map<std::string, std::vector<std::queue<int> > > > >... попробуй пойми, что автор этого имел в виду  smile
PM   Вверх
tonchitos
Дата 19.3.2008, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 447
Регистрация: 24.2.2007

Репутация: нет
Всего: 40



я организовала успешно поиск одного элемента дерева в другом, но того кто дал мне задание это не устроило

три варианта на выбор было мне предложено.
У каждого элемента дерева должен быть свой идентификатор и этот идентификатор надо связать с каждым элементом в графическом дереве и поиск осуществлять по индивидуальному идентификатору.

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

Вариант с памятью самый симпотичный в смысле ненужности поиска. В общем что предпочесть и есть ли поле в триконтроле в котором можно хранить некую информацию типа лонг например?

Добавлено через 52 секунды
Код


namespace GUI
{

class Node 
{
public:
    std::vector<Node> childs;
    std::string Name;
    int pole1;
    int pole2;
    int level;
    int size;
    long identificator; 
    static long lastIdent;
public:

    Node();
    
    Node (const Node &obj)
    {
        childs = obj.childs;
        Name = obj.Name;
        pole1 = obj.pole1;
        pole2 = obj.pole2;
        level = obj.level;
        size = obj.size;
    }

    void LoadData(std::string str)
    {
        Name=str;
    }
    
    int GetNumChilds ()
    {
        return childs.size();
    }

    const Node & GetChild (int pos) const
    {
        return childs[pos];
    }

    Node & GetChild (int pos)
    {
        return childs[pos];
    }

    std::ostream& printFile(std::ostream& stream, unsigned int tab) const;
    void readFile (std::istream &stream); // Return last identificator
    bool insertChild (Node & element );
    bool removeChild (int pos);    
    Node & operator = (const Node & from);

    ~Node();

    };

}


вот сама деревяшка


--------------------
– Люди забыли эту истину, – сказал Лис, – но ты не забывай: ты навсегда в ответе за всех, кого приручил.
PM MAIL   Вверх
baldina
Дата 19.3.2008, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



вау! оказывается, возможны варианты... а я постеснялся предложить  smile 
Цитата

У каждого элемента дерева должен быть свой идентификатор 

это правильное решение. обрати внимание: тебе видимо нужна двунаправленная связь: щелкаем по элементу в treectrl - работаем с деревом в памяти, изменяем дерево в памяти - обновляем treectrl.
Искать нужно в любом случае, либо хранить обе ссылки. Однако это вид должен все знать про документ, а не наоборот. Так что присваиваем идентификаторы узлам дерева и храним их как ссылки в treectrl.
Производительность: когда манипулируем с treectrl (пользователь щелкнул на элементе) скорость неважна, т.к. пользователь 0.1 сек всегда подождет.
Когда обновляем treectrl - стараемся это делать редко, когда все операции завершены и, возможно, просто перестраиваем treectrl - тут искать не надо, просто обходим.
Цитата

есть ли поле в триконтроле в котором можно хранить 

есть. ищи SetItemData/GetItemData

Добавлено @ 22:19
PS. Тебя явно одновременно воспитывают и проверяют, и вообще ведут себя грамотно  smile 
Не расслабляйся  smile

Добавлено @ 22:23
PPS Помню года 3-4 назад пришлось оптимизировать фрагмент кода: прога тормозила в процессе расчета. Оказалось: было дерево ~100 узлов, при этом было примерно ~1000000!! обращений в дерево. А дело было в том, что данные хранилось непосредственно в treectrl, никакой доп. информации не было, и при необходимости получить нужный узел производился последовательный просмотр содержимого дерева...  smile 

Это сообщение отредактировал(а) baldina - 19.3.2008, 22:25
PM MAIL   Вверх
bsa
Дата 20.3.2008, 00:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



tonchitos, в качестве идентификатора уже служит имя нода (у тебя же дети одного нода не могут носить одно имя, так?)... И именно этот способ я предлагал использовать в пред-предыдущем своем сообщении (я его довольно невнятно сформулировал, правда). Ты каждый элемент графического дерева ассоциируешь с именем нода в памяти, а поиск производишь рекурсивно:
Код
typedef std::list<std::string> StringList;
Node* Node::find(StringList::const_reverse_iterator p, StringList::const_reverse_iterator rend)
{
    if (p == rend) //условие выполнится, когда будет достигнут конец списка
        return this; //список пройден до конца, возвращаем
    ++p;
    for(std::vector<Node>::const_iterator i = childs.begin(), end = childs.end(); i != end; ++i)
        if (i->Name == *p)
            return i->find(p, rend); //найден потомок с нужным именем - продолжаем поиск среди его потомков
    return 0; //нод не найден
}
Ну сделай наконец typedef для std::vector<Node> (твой работодатель тебе дополнительный плюс поставит за это)!!!
И тебе точно нужно поле level? Я так понимаю, особой смысловой нагрузки оно не несет.
PM   Вверх
tonchitos
Дата 20.3.2008, 00:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 447
Регистрация: 24.2.2007

Репутация: нет
Всего: 40



bsa,  имя нода не катит оказывается  smile , мне сказали что могут совпадать имена сколько влезет. Поэтому нужен идентификатор.


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

Уходя с работы я еще поговорила и от моих трех вариантов один остался.

Цитата

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

этот вариант мне предложили сами, но не одобряют тк память. Люди, если ресайза избежать можно быть за память уверенной? Фиг его знает как там вектор шалит.
Цитата

 третий вариант - мой, для каждого узла дерева хранить HTREEITEM графического узла (тогда тож искать надо).

вариант отмели, тк у каждого дерева может быть несколько графических деревьев. воть.

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

В итоге катит первый вариант с идентификаторами. Возможен второй, но под вопросом. 



--------------------
– Люди забыли эту истину, – сказал Лис, – но ты не забывай: ты навсегда в ответе за всех, кого приручил.
PM MAIL   Вверх
tonchitos
Дата 20.3.2008, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 447
Регистрация: 24.2.2007

Репутация: нет
Всего: 40



теперь новый момент:

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

варианты.

Код

namespace GUI
{

class Node 
{
public:
    std::vector<Node> childs;
    std::string Name;
    int pole1;
    int pole2;
    int level;
    int size;
    long identificator; 
    static long lastIdent;
public:

    Node();
    
    Node (const Node &obj)
    {
        childs = obj.childs;
        Name = obj.Name;
        pole1 = obj.pole1;
        pole2 = obj.pole2;
        level = obj.level;
        size = obj.size;
    }
...............
.....................
.......................

    ~Node();

    };

class Root
{
public:
    std::vector<Node> childs;
    long lastIdent;
public:

//конструкторы деструкторы то се


}

}




и потом :

GUI::Node node;
GUI::Root root;
.................
................
root.childs.resize(n);
и так работать

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

Тогда лучше отнаследовать?

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

Добавлено через 36 секунд
bsa, тайпдеф сделаю!!!! утром займусь этим обязательно.


--------------------
– Люди забыли эту истину, – сказал Лис, – но ты не забывай: ты навсегда в ответе за всех, кого приручил.
PM MAIL   Вверх
bsa
Дата 20.3.2008, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



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

В данном случае рут просится быть наследником нода. Хотя, если тебе нужно следить за обращениями к нодам, то лучше использовать не наследование, а агрегацию (включение), но те так как у тебя сделано:
Код
namespace GUI {
class Root
{
public:
      Root(){}
      ~Root(){}
      const Node& getNode() const { return node; }
      Node& getNode() { return node; }
private:
      Node node;
};
}
В данном случае, в getNode() можно запихать уже фиксирование того, к кому происходило обращение...

typedef сделать не так уж и сложно (Правка - Найти и заменить: "std::vector<Node>" на "Nodes", а потом добавить в класс typedef std::vector<Node> Nodes; - и всё).
PM   Вверх
tonchitos
Дата 20.3.2008, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 447
Регистрация: 24.2.2007

Репутация: нет
Всего: 40



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


--------------------
– Люди забыли эту истину, – сказал Лис, – но ты не забывай: ты навсегда в ответе за всех, кого приручил.
PM MAIL   Вверх
bsa
Дата 20.3.2008, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



tonchitos, у меня в последнем примере сделана агрегация.  smile 
PM   Вверх
tonchitos
Дата 20.3.2008, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 447
Регистрация: 24.2.2007

Репутация: нет
Всего: 40



сорри, не оч поняла смысл гетНода... Объясните плиз. smile

Добавлено через 2 минуты и 11 секунд
class Root
{
public:
      Root()
      {
      }
      ~Root()
      {
      }
      const Node& getNode() const 
      { 
          return node; 
      }
      Node& getNode() 
      { 
          return node; 
      }
private:
      Node node;
      long lastIdent; // как предполагается менять его, если у меня в ноде по идее меняться должен и не в ноде тоже
};


--------------------
– Люди забыли эту истину, – сказал Лис, – но ты не забывай: ты навсегда в ответе за всех, кого приручил.
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0709 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.