Russian Qt Forum
Октябрь 02, 2024, 13:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Lookup  (Прочитано 10638 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Март 10, 2012, 15:25 »

Добрый день

Есть контейнер элементы которого имеют какой-то атрибут, пусть цвет. Значение атрибута не уникально, напр в исходном контейнере 4 элемента с красным цветом, 2 с синим и.т.п.

Нужно: имея элемент быстро найти все с тем же цветом.  напр элемент красный - пробежаться по всем остальным красным. Исходный контейнер сортировать/изменять нельзя, создавать любые доп данные - можно.

Спасибо
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4744



Просмотр профиля WWW
« Ответ #1 : Март 10, 2012, 15:46 »

можно сразу завести словарь, ключами которого будут атрибуты, а значениями - векторы/множества указателей на элементы с данным атрибутом
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
qt_user
Гость
« Ответ #2 : Март 10, 2012, 16:33 »

std::multimap
+
pair<const_iterator,const_iterator>
   equal_range ( const key_type& x ) const;
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Март 10, 2012, 19:26 »

Рекомендации понятны, спасибо. А нельзя это сделать без всякого STL и/или Qt, просто на массивах/new? Или так будет сложно/громоздко?
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4744



Просмотр профиля WWW
« Ответ #4 : Март 11, 2012, 01:14 »

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

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Bepec
Гость
« Ответ #5 : Март 11, 2012, 07:01 »

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

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

PS напиши свой собственный мультимап.
Записан
Disa
Гость
« Ответ #6 : Март 11, 2012, 10:47 »

Вопрос почти по теме, если контейнер не модифицировать после инициализации и если элементы уникальные - что предпочтительнее: set <pair> или все же map?

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Март 11, 2012, 10:56 »

Нельзя модифицировать исходный контейнер, но снабдить элемент доп данными - можно
Записан
Bepec
Гость
« Ответ #8 : Март 11, 2012, 12:02 »

уникальные - map.
повторяющиеся - pair или мультимап.
Записан
qt_user
Гость
« Ответ #9 : Март 11, 2012, 13:14 »

Вопрос почти по теме, если контейнер не модифицировать после инициализации и если элементы уникальные - что предпочтительнее: set <pair> или все же map?


я думаю если ключи допустим строка, оператор сравнения для std::string будет работать намного быстрее,
чем для std::pair<std::string, std::string>

хотя это больше зависит от задачи: если можно выделить один ключ - тогда это std::map,
если два значения равноправны и нельзя сказать что из них является ключом - тогда лучше
std::set<std::pair<...> >
« Последнее редактирование: Март 11, 2012, 13:17 от qt_user » Записан
Disa
Гость
« Ответ #10 : Март 11, 2012, 15:00 »

Ну хотя получается, что грубо у всех множест nlogn для поиска, но и все себя перестраивают при добавлении эллемента.
И еще, как я понимаю в зависимости от константы перед nlogn будет сильно зависеть как контейней будет вести себя при разном количестве эллементов. Не смог обнаружить какие-то тесты по сравнению скорости работы алгоритмов и операторов, мб кому-то попадались на глаза?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Март 11, 2012, 16:13 »

И еще, как я понимаю в зависимости от константы перед nlogn будет сильно зависеть как контейней будет вести себя при разном количестве эллементов. Не смог обнаружить какие-то тесты по сравнению скорости работы алгоритмов и операторов, мб кому-то попадались на глаза?
Это катастрофически зависит от конкретной реализации, часто также от опций компилятора. Напр (не к ночи будь сказано) у MS это может отличаться на порядки debug/release

На мой взгляд лучшее средство - тщательно продумывать организацию данных, а не ляпать контейнерами абы как. О чем, кстати, и данная тема  Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Март 12, 2012, 16:18 »

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

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

PS напиши свой собственный мультимап.
Написал  Улыбающийся

Код
C++ (Qt)
struct CDataLookup {
QList <CElement> mData;    // исходный контейнер
QList <CElement *> mLookup; // указатели отсортированы по атрибуту (цвету)
};
 
// использование
void CDataLookup::ScanByColor( CElement & elem )
{
 for (int i = elem.mLookupIndex; i < mLookup.size(); ++i) {
   if (mLookup[i]->mColor != elem.mColor) break;
   DoSomething(mLookup[i]);  // указатель на элемент с тем же цветом что и elem
 }
}
 

Edit: а можно и вообще не хранить сортированный массив
« Последнее редактирование: Март 12, 2012, 16:41 от Igors » Записан
qt_user
Гость
« Ответ #13 : Март 13, 2012, 00:53 »

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

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

PS напиши свой собственный мультимап.
Написал  Улыбающийся

Код
C++ (Qt)
struct CDataLookup {
QList <CElement> mData;
QList <CElement *> mLookup;
};
 
void CDataLookup::ScanByColor( CElement & elem )
{
   for (int i = elem.mLookupIndex; i < mLookup.size(); ++i) {
     if (mLookup[i]->mColor != elem.mColor) break;
   DoSomething(mLookup[i]);
 }
}
 

Edit: а можно и вообще не хранить сортированный массив
это конечно все хорошо, но зачем нужен подобный велосипед если есть тот же
мультимап?
void CDataLookup::ScanByColor( CElement & elem ) - я так понимаю перед каждым вызовом
этой ф-ции нужно заново сортировать QList <CElement *> mLookup; ?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Март 13, 2012, 11:08 »

это конечно все хорошо, но зачем нужен подобный велосипед если есть тот же
мультимап?
void CDataLookup::ScanByColor( CElement & elem ) - я так понимаю перед каждым вызовом
этой ф-ции нужно заново сортировать QList <CElement *> mLookup; ?
Нет, достаточно один раз отсортировать и вписать в каждый элемент индекс указателя на первый с тем же цветом в сортированном массиве. Хотя есть ходы и получше.

Небольшая разница между "имея элемент" и "имея (значение) цвета" позволяет обойтись без поиска вообще. А от мультимапы я балдею Улыбающийся Ну ладно, допустим даже "искать по цвету" - но тогда почему не lower_bound? На худой конец С-шный bsearch. Тот же логарифм но сортированный массив указателей куда дешевле чем любой ассоциативный контейнер.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.303 секунд. Запросов: 23.