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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Контейнер уникальных значений без operator< 
V
    Опции темы
borisbn
Дата 24.6.2011, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



День добрый !
Есть задачка: имеется структура
Код

struct X {
    int a;
    int b;
    bool operator==( const X & that ) const {
        return this->a == that.a && this->b == that.b;
    }
};

нужно хранить в некоем контейнере такие структуры, но только уникальные.
Т.е. чтобы выполнялось условие (псевдокод)
Код
!(s[ i ] == s[ j ]), где i != j

вроде бы идеально подходит std::set, но он требует operator< для структуры, а меня это не устраивает по двум причинам:
1. Мне совершенно не важно, будут ли структуры храниться в отсортированном виде, т.к. их количество будет 20...30 и добавление в контейнер будет происходить только в начале программы. А время поиска конкретного элемента для данной задачи совершенно не критично.
2. Я не знаю как сравнить две структуры на предмет меньше ли одна или нет, т.к. оба поля в принципе равнозначны.

Смотрел на QSet (Qt), но он требует ф-цию хеша из моей структуры, а я тем более не представляю, как её сделать...

Можно, конечно, повелосипедировать: аггрегировать вектор и написать ф-цию добавления и поиска... но хочется сначала выяснить, нет ли готового решения

Спасибо.

P.S. boost просьба не предлагать соответствующего coder'а прошу не обижаться smile

Это сообщение отредактировал(а) borisbn - 24.6.2011, 10:41


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
rudvil
Дата 24.6.2011, 10:47 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 155
Регистрация: 20.11.2009
Где: Latvia/Riga

Репутация: 2
Всего: 3



Цитата(borisbn @  24.6.2011,  10:40 Найти цитируемый пост)
но хочется сначала выяснить, нет ли готового решения

Если есть поддержка C++0x
Код
#include <unordered_set>

--------------------
xor
PM MAIL Skype   Вверх
Sahab
Дата 24.6.2011, 10:49 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(rudvil @  24.6.2011,  10:47 Найти цитируемый пост)
unordered_set

а для него хеш не нужно реализовывать?  smile 

Это сообщение отредактировал(а) Sahab - 24.6.2011, 10:51
PM MAIL   Вверх
rudvil
Дата 24.6.2011, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 155
Регистрация: 20.11.2009
Где: Latvia/Riga

Репутация: 2
Всего: 3



Цитата(Sahab @ 24.6.2011,  10:49)
Цитата(rudvil @  24.6.2011,  10:47 Найти цитируемый пост)
unordered_set

а для него хеш не нужно реализовывать?  smile

Точно... это же не POD.
Спасибо за поправку.
--------------------
xor
PM MAIL Skype   Вверх
Sahab
Дата 24.6.2011, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



мне только непонятно... если 
Цитата

Мне совершенно не важно, будут ли структуры храниться в отсортированном виде


то чем не подходит?
Код

    bool operator < ( const X & that ) const {
       return this->a < that.a && this->b < that.b;
    }


PM MAIL   Вверх
RastaDja
Дата 24.6.2011, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Sahab @  24.6.2011,  11:56 Найти цитируемый пост)
то чем не подходит?
код C++
    bool operator < ( const X & that ) const {
       return this->a < that.a && this->b < that.b;
    }

потому что a и b - несут независимую информацию
например а - масса, b - высота
какой объект больше? - тот что тяжелее, или выше?


--------------------
The more closely you look at one thing, the less closely can you see something else.
PM MAIL   Вверх
borisbn
Дата 24.6.2011, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(Sahab @  24.6.2011,  10:56 Найти цитируемый пост)

то чем не подходит?
bool operator < ( const X & that ) const {
       return this->a < that.a && this->b < that.b;
    }

в принципе, я уже дошёл до этого, но, т.к. мне действительно не важно, то можно и return true сделать...
то, что можно так заюзать set - я уже понял (мало того, уже сделал), но хотелось бы выяснить не будет ли это overhead'ом? Нет ли стандартного (специально обученного, заточенного) решения для этой задачи.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
azesmcar
Дата 24.6.2011, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(borisbn @  24.6.2011,  11:20 Найти цитируемый пост)
то можно и return true сделать

ни в коем случае.
Цитата

For all algorithms that take Compare, there is a version that uses operator< instead. That is, comp(*i, *j) != false defaults to *i < *j != false.
For the algorithms to work correctly, comp has to induce a strict weak ordering on the values. The term strict refers to the requirement of an irreflexive relation (!comp(x, x) for all x), and the term
weak to requirements that are not as strong as those for a total ordering, but stronger than those for a partial ordering. If we define equiv(a, b) as !comp(a, b) && !comp(b, a), then the requirements
are that comp and equiv both be transitive relations:

— comp(a, b) && comp(b, c) implies comp(a, c)

PM   Вверх
borisbn
Дата 24.6.2011, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



azesmcar, спасибо. Я правильно понял, что return true нельзя, т.к. set (ну или там алгоритмы поиска - не важно) может вместо operator== создать собственный
Цитата
equiv(a, b) as !comp(a, b) && !comp(b, a)

и тогда он просто не найдёт нужный мне элемент, а при return false будет всегда находить первый ?

Что тогда посоветуете ?

P.S. Откуда цитата ?

Это сообщение отредактировал(а) borisbn - 24.6.2011, 13:21


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Earnest
Дата 24.6.2011, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата

 bool operator < ( const X & that ) const {
       return this->a < that.a && this->b < that.b;
    }

Это неправильно, нужно так: 
Код

 if this->a == that.a return this->b < that.b;
 else return this->a < that.a;

Сравнение обязательно должно быть транзитивным, иначе в твоем сете будет каша.

Есть много случаев, когда упорядочивание нужно чисто для хранения. 
Логический смысл тогда не важен, главное, чтобы упорядочивание было однозначным и непротиворечивым.
Если POD, как у тебя, и не содержит double, тогда я не парюсь, а просто использую memcmp. Условие, которое привел
azesmcar, автоматически выполняется. Кстати, можно тогда не писать свой == (потому что он уже есть - !< && !>).

Кстати, если определить свою структуру через std::pair (вместо именованных членов), то оператор сравнения генерируется автоматически, именно как я написала. Естественно, если сравнение для членов не определено, возникают проблемы...
Другое дело, если стандартный оператор < не подходит, как например для даблов... 

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

    static size_t Hash (const POINT& pt) 
    { 
        return (__int64)pt.x * 2531011 + (__int64)pt.y * 214013;
    }

Могут быть и другие числа (не помню уже откуда, давно содрала и с тех пор счастливо использую); разбрасывает замечательно, даже если точки близки.
Но только имей в виду, что хэш обычно жрет памяти побольше, чем просто map\set. Если это важно.


--------------------
...
PM   Вверх
borisbn
Дата 24.6.2011, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Earnest, я для примера вривёл 2 поля. На самом деле у меня их 6. Представляешь, что за монстр получится в операторе < ?

Цитата(Earnest @  24.6.2011,  14:03 Найти цитируемый пост)
Кстати, можно тогда не писать свой ==

не то, чтобы можно, а бессмысленно, т.к., судя по всему, std::set использует только меньше. Говорю это потому, что определил только оператор меньше, и у меня всё скомпилялось и добавление и поиск...


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Sahab
Дата 24.6.2011, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата

какой объект больше? - тот что тяжелее, или выше? 


это и ежу понятно...
но в данном контексте это было не важно
PM MAIL   Вверх
borisbn
Дата 24.6.2011, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(Sahab @  24.6.2011,  14:19 Найти цитируемый пост)
но в данном контексте это было не важно

важно
Sahab, 
Цитата(Sahab @  24.6.2011,  10:56 Найти цитируемый пост)
то чем не подходит?
bool operator < ( const X & that ) const {
    return this->a < that.a && this->b < that.b;
}

тем, что если a1 < a2, а b1 > b2, то обе структуры будут считаться больше другой. Может и зацикливание произойти.


Это сообщение отредактировал(а) borisbn - 24.6.2011, 14:24


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Earnest
Дата 24.6.2011, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(borisbn @  24.6.2011,  15:12 Найти цитируемый пост)
что определил только оператор меньше, и у меня всё скомпилялось и добавление и поиск... 

Скомпилировалось - не значит правильно работает. Чего бы не скомпилироваться, если формальный синтаксис соблюден.
Еще раз, приведенный в самом начале оператор < - неправильный, потому что не транзитивный. Можешь нарваться не сразу, и будешь долго ломать голову, откуда лажа.
Грубо говоря, даже уникальность хранения может нарушаться при таком операторе: все зависит от того, в каком состоянии будет дерево и по какому пути пойдет сравнение.
Если членов много, и это POD, можно использовать memcmp, как я писала.
Цитата(borisbn @  24.6.2011,  15:12 Найти цитируемый пост)
не то, чтобы можно, а бессмысленно, т.к., судя по всему, std::set использует только меньше. 

set действительно использует только "меньше". Я имела в виду, что может сравнение на равенство нужно тебе зачем-то еще. 

Цитата(borisbn @  24.6.2011,  15:12 Найти цитируемый пост)
 Представляешь, что за монстр получится в операторе < 

Да не намного страшнее, чем оператор проверки равенства - принцип тот же, упорядочиваешь по первой, если она равна - по второй и т.д.
Только удобнее записать немного по-другому:
Код

if first != rhs.first return first < rhs.first
else if second != rhs.second return second < rhs.second
и т.д.

Ну или хэш-контейнеры использовать.


--------------------
...
PM   Вверх
borisbn
Дата 24.6.2011, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(Earnest @  24.6.2011,  14:03 Найти цитируемый пост)
тогда я не парюсь, а просто использую memcmp

хммммм. а ведь идея:
Код

bool operator < ( const X & that ) const {
    int a_this[ 6 ];
    a_this[ 0 ] = this->field1;
    ...
    a_this[ 5 ] = this->field6;
    int a_that[ 6 ];
    a_that[ 0 ] = that.field1;
    ...
    a_that[ 5 ] = that.field6;
    return memcmp( a_this, a_that, sizeof( a_this ) ) < 0;
}


Добавлено через 9 минут и 19 секунд
Цитата(Earnest @  24.6.2011,  14:30 Найти цитируемый пост)
Скомпилировалось - не значит правильно работает. Чего бы не скомпилироваться, если формальный синтаксис соблюден.Еще раз, приведенный в самом начале оператор < - неправильный, потому что не транзитивный. Можешь нарваться не сразу, и будешь долго ломать голову, откуда лажа.

это то понятно (чай не первый раз замужем). под "скомпилировалось" я имел в виду, что std::set больше ничего не требует. и не более того.

Цитата(Earnest @  24.6.2011,  14:30 Найти цитируемый пост)
Я имела в виду, что может сравнение на равенство нужно тебе зачем-то еще. 

теперь ясно. нет. не нужен.

Цитата(Earnest @  24.6.2011,  14:30 Найти цитируемый пост)
Ну или хэш-контейнеры использовать.

тогда такой вопрос:
Цитата(borisbn @  24.6.2011,  10:40 Найти цитируемый пост)
Смотрел на QSet (Qt), но он требует ф-цию хеша из моей структуры, а я тем более не представляю, как её сделать...




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Страницы: (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.0864 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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