IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным. В описании темы указываем язык!!!

> Обход иерархического дерева вниз., дерево из QTreeWidgetItem
Andrewshkovskii
сообщение 27.12.2010 0:43
Сообщение #1


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Как всегда рассчитываю на помощь volvo smile.gif
Есть дерево, в нем возможны 3 элемента
3. Элемент типа 1003 - критерий, у этого элемента есть некоторое значение.
2. Элемент типа 1002 - это подгруппа (т.е. у неё есть род. группа) и она содержит только элементы типа 1003, у неё есть значение(вес).
1. Элемент типа 1001 - Группа верхнего уровня (в неё входят либо только элементы 1002 - подгруппы, либо только элементы 1003 - критерии), у него есть значение(вес).

Глубина/вложенность дерева может быть бесконечно глубокой.

Какой проход необходимо реализовать :
1. Необходимо подсчитать значениях все элементов 1003. (значение_критериев_группы)
2. Умножить значение элементов группы на родительскую группу. (значение_группы или значение_подгруппы)
2.1 Если эта группа вложена в другую группу(т.е. является подгруппой) необходимо умножить её значение на значение родительской группы
3. И так , пока не дойдем до корня.
Вот пример изображения на картинке, как элементы взаимодействуют с собой(это QTreeWidget).
Изображение

Я набрасал логику алгоритма в текстовом блокнотике в виде "псевдокода", хотелось бы что бы мне помогли понять, правильно ли я понял алгоритм
Код
Подсчитать группы, для этого нужен рекурсивный алгоритм обхода дерева групп критерией :
        //Берем список топ-левел айтемов.
        //для каждого айтема этого списка
        //обнулить : значение_группы, значение_критериев_подгруппы, значение_критериев_группы.
        //получаем список его чилдов
          //функция_1(список айтемов) :
            //для каждого из списка
            //если тип айтема 1001(группа, у неё есть подгруппы либо только критерии) получаем количество его чилдов если оно >0 (это исключит пустые группы)
                //получаем список чилдов.
                  //вызываем функция_1 для этого списка.
                //если значение_критериев_подгруппы != 0 (Значит была подсчитана подгруппа)
                    //значение_группы+=вес_группы*значение_подгруппы.
                //иначе (значит не было подгрупп)
                    //значение_группы+=вес_группы*значение_критериев_группы
            //иначе если тип айтема 1002(подгруппа) получаем количество его чилдов если оно >0 (это исключит пустые группы), все его чилды 100% критерии
                //для каждого критерия(чилда)
                    //если его значение !=0
                        //значение_критериев_группы+=взвешенное_значение_критерия_по_году_рейтинга
                //значение_подгруппы=вес_подгруппы*значение_критериев_группы
            //иначе если тип айтема 1003(критерий) то мы нашли критерий и для него (иначе это пустая группа, но этого лучше не допускать)
                //если его значения !=0 (но этого тоже лучше не допускать)
                    //значение_критериев_группы+=взвешенное_значение_критерия_по_году_рейтинга
        //значение верхней группы+=вес_верхней_группы*значение_группы.

Но проблема в том, что в Qt (4.7.1) нельзя просто получить список детей элемента(только итерировать по ним, либо получить, но они удаляться из виджета/айтема). Я попробую написать алгоритм, но прощу помощи здесь, вдруг что-то упустил..

Сообщение отредактировано: Andrewshkovskii - 27.12.2010 1:25
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
Andrewshkovskii
сообщение 27.12.2010 21:27
Сообщение #2


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Поправил алгоритм установки типа, теперь все верно.
Вот только алгоритм подсчета работает не верно, и почему-то один узел проходит 2 раза, но по разным критериям..
void MainWindow::function_1(const QTreeWidgetItem* item,const int &year )
{
QTreeWidgetItem *item2;
QTreeWidgetItem *item3;
double mainValue;
for(int i=0;i<item->childCount();++i)//для каждого чилда верхней группы
{
item2 = item->child(i);//получаем чилда
qDebug () << "for group "+item->text(0);
if(item2->type()==1001 && item2->childCount() > 0)//если этот чилд - группа, и количество его чилдов >0
{
qDebug() << "item " +item2->text(0) + " is mainGroup";
for(int j=0;j<item2->childCount();++j)//для каждого его чилда
{
item3 = item2->child(j);//получаем чилда
function_1(item3,year);//вызываем рекурсивную функцию.
}
if(subGroupValue!=0){//если значение подгруппы !=0 (т.е. были подгруппы)
groupValue+=groupWeight_(criteriaGroupMap.value(item2))*subGroupValue;
subGroupValue=0;
}
else//иначе не было подгрупп, и считаем чилдов.
groupValue+=groupWeight_(criteriaGroupMap.value(item2))*groupCriteriaValue;
}else if(item2->type()==1002 &&item2->childCount()>0)//иначе если айтем является подгруппой, и у него критериев >0
{
qDebug() << item2->text(0) + " is subGroup";
for(int j=0;j<item2->childCount();++j)//для каждого из этих критериев
{
item3=item2->child(j);//получаем критерий
qDebug() << item3->text(0) +" is criteria from group " +item2->text(0);
groupCriteriaValue+=weightedCriteriaValue_(criteriaMap.value(item3),year);
}
subGroupValue=groupWeight_(criteriaGroupMap.value(item2))*groupCriteriaValue;//вес группы в которой расположены критерии
}else if(item2->type()==1003)//иначе в группе толко критерии
{
qDebug() << item2->text(0) + " is criteria from " + item->text(0);
groupCriteriaValue=0;
groupCriteriaValue+=weightedCriteriaValue_(criteriaMap.value(item2),year);
}
}
// groupValue+=groupWeight*groupValue;//значения для item, т.е. элемента верхнего уровня.-- подумать о том, что это значения для высшего УРОВНЯ.
}

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

Вот что выводит алгоритм для этих значений :Изображение
Цитата
"for group Научно-исследовательская работа"
"item Подготовка научных кадров is mainGroup"
"for group Подготовка соискателей ученых степеней"
"Эффектиновсть подготовки is subGroup"
"Эффектиновсть аспирантуры is criteria from group Эффектиновсть подготовки"
"Эффективность работы по подготовке докторов наук is criteria from group Эффектиновсть подготовки"
"for group Подготовка соискателей ученых степеней"
"Участие в подготовке научных кадров is subGroup"
"Подготовка аспирантов is criteria from group Участие в подготовке научных кадров"
"Участие в советах по защите диссертаций is criteria from groupУчастие в подготовке научных кадров"
"for group Научная работа студентов"
"Участие в договорных НИОКР is criteria from Научная работа студентов"
"for group Научная работа студентов"
"Доклады на неделе науки и конференциях is criteria from Научная работа студентов"
"for group Научно-исследовательская работа"
"Научная работа is subGroup"
"Объем НИОКР is criteria from group Научная работа"
"Участие в изобретательской деятельности is criteria from group Научная работа"
"for group Научно-исследовательская работа"
"Научные труды is subGroup"
"Доклады is criteria from group Научные труды"
"Монографии is criteria from group Научные труды"
"Статьи is criteria from group Научные труды"

А н нет, это я тупанул, 2 раза не проходит..только считает все равно не верно.
Может стоит оформить эту функцию в таком виде , что бы она возвращала значения подгрупп?
О том, как это все должно считаться :
Приходя в группу типа 1002 или типа 1001 у которой только критерии внутри,
мы суммируем взвешенные значения критериев группы, умножаем на вес группы. Получившиеся значение умножаем на вес родительской группы (если таковая имеется) до тех пор, пока не дойдем до корня, после чего это значение прибавляется результирующему значению всех верхних групп( "совсем" верхних, т.е там будет main +=значение (Научно-исследовательская работа)+etc..)..
Volvo, подскажи rolleyes.gif

Сообщение отредактировано: Andrewshkovskii - 27.12.2010 22:15
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

Сообщений в этой теме


 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия 28.07.2025 9:14
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"