Re[4]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 15:14
Оценка: 28 (1)
Здравствуйте, Кодт, Вы писали:

К>1) unordered_* и hash_* есть в STL?


hash_ это расширение некоторых STL. unordered_ будут в STL и есть в Boost.

К>2) какая временная сложность у unordered_multiset?


Amortized constant.
На практике multimap ощутимо быстрее map.

К>3) как по заданному предикату сравнения (равенства или порядка, неважно) сделать хеш-функцию?


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

К>Например, есть функция strcoll, сравнивающая строки в соответствие с текущей (или заданной) локалью.

К>Я надеюсь, что она корректно обрабатывает лигатуры, умляуты и т.п.
К>То есть, немецкие слова Roentgen и Röntgen попадут в одну корзину.

Нет тут проблемы. Достаточно привести к виду, где Roentgen и Röntgen будут одинаковы.
strxfrm делает это.

К>Хеш-функция, читающая строку посимвольно, даст разные значения для слитного и раздельного написания умляута. Получится более сильный предикат, чем искомый — а должен быть более слабый.

К>Значит, нам нужна хеш-функция, читающая строку порциями, да ещё в зависимости от локали.
К>Давайте попросим разработчиков ОС и компиляторов, чтоб они включили эти хеш-функции в соответствующие системные библиотеки? Дело-то хорошее...

Хеширование результата strxfrm уже долшно работать.
Русский военный корабль идёт ко дну!
Re[7]: Зачем существует std::multiset
От: jazzer Россия Skype: enerjazzer
Дата: 16.06.08 16:44
Оценка: 3 (1)
Здравствуйте, Alexander G, Вы писали:

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


J>>очередь сообщений, упорядоченная по таймстемпу с плохим разрешением


AG>Это priority_queue, нет ?


Если я не ошибаюсь, priority_queue постоянно двигает объекты (естественно, как же иначе их в массиве располагать), в отличие от дерева.
А сложность и там и там — логарифм (правда, в дереве еще есть такая хорошая вещь как hinted insertion)
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Зачем существует std::multiset
От: R.K. Украина  
Дата: 15.06.08 17:01
Оценка: 2 (1)
Здравствуйте, Alexander G, Вы писали:

AG>Кто-нибудь можеть привести пример разумного применения?


Возможно, для хранения частично упорядоченного множества. Например:
struct stri_less
    : public std::binary_function<std::string, std::string, bool>
{
    bool operator()(const std::string &a, const std::string &b)
    { return _stricmp(a.c_str(), b.c_str()) < 0; }
};

std::multiset<std::string, stri_less> mset;
mset.insert("case");
mset.insert("Case");
mset.insert("caesar");
mset.insert("cASe");
mset.insert("CasE");
mset.insert("casual");

mset.equal_range("case"); // интервал со всеми видами "case"
You aren't expected to absorb this
Re[12]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 17.06.08 12:43
Оценка: 2 (1)
Здравствуйте, igna, Вы писали:

I>Здравствуйте, Alexander G, Вы писали:


AG>>В любом случае, если у слов есть значения, нужен multimap, а не multiset.


I>Чем multiset хуже?


Тем, что в его find, upper_bound, и другие нужно передавать то же, что хранится в нём, т.е. слово со значением.
В multimap поиск по слову находит слово и значение.
Русский военный корабль идёт ко дну!
Re: Зачем существует std::multiset
От: jazzer Россия Skype: enerjazzer
Дата: 15.06.08 15:43
Оценка: +1
Здравствуйте, Alexander G, Вы писали:

AG>Кто-нибудь можеть привести пример разумного применения?


это просто упорядоченная коллекция объектов с соответствующими гарантиями сложности вставки/удаления/поиска.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Зачем существует std::multiset
От: Mazay Россия  
Дата: 15.06.08 17:12
Оценка: +1
Здравствуйте, Roman Odaisky, Вы писали:

Z>>Задача: У Маши в корзине 4 яблока. Мама положила ей в корзинку еще 3 груши. Сколько фруктов в корзинке у Маши?


RO>Здесь нужен std::map<Fruit, std::size_t>, а не multiset.


size() может иметь сложность O(1), а сумма по std::map<Fruit, std::size_t> — O(n)
Главное гармония ...
Re[4]: Зачем существует std::multiset
От: рыбак  
Дата: 16.06.08 07:53
Оценка: +1
Здравствуйте, Zigmar, Вы писали:

Z>Здравствуйте, Alexander G, Вы писали:

AG>>Зачем может пригодиться multiset — не понимаю.

Z>Задача: У Маши в корзине 4 яблока. Мама положила ей в корзинку еще 3 груши. Сколько фруктов в корзинке у Маши?

Z>Решение:
Z>
Z>enum Fruit{Apple, Pear, Kiwi};
Z>struct Masha_t {
Z>  std::multiset<Fruit> basket;
Z>}Masha;

Z>for(int i=0; i<4; ++i)
Z>  Masha.basket.insert(Apple);

Z>for(int i=0; i<3; ++i)
Z>  Masha.basket.insert(Pear);

Z>size_t answer = Masha.basket.size();
//  более убедительно:
  size_t nApples = Masha.basket.count(Apple);
Z>

Z>
Re: Зачем существует std::multiset
От: maq Россия http://www.maqdev.com
Дата: 16.06.08 08:26
Оценка: :)
AG>Кто-нибудь можеть привести пример разумного применения?

Пример: есть заказ и его составляющие, т.е. отношение один ко многим.

Можно хранить составляющие в multiset, причем ключем будет ссылка на заказ (ID заказа), тогда по ID заказа можно эффективно выбрать все его составляющие.
Re[4]: Зачем существует std::multiset
От: Cyberax Марс  
Дата: 16.06.08 15:01
Оценка: +1
Здравствуйте, Кодт, Вы писали:

К>Значит, нам нужна хеш-функция, читающая строку порциями, да ещё в зависимости от локали.

Обычно это решается нормализацией строк в хэш-функции.
Sapienti sat!
Re[8]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 16:44
Оценка: +1
Здравствуйте, igna, Вы писали:

AG>>Всё равно, если пользователь не добавляет слова то лучше вектор.


I>Почему?


А чем multiset::equal_range лучше std::equal_range ?
std::vector — дефолтный контейнер, это использование других вместо него нужно обосновывать.
Русский военный корабль идёт ко дну!
Зачем существует std::multiset
От: Alexander G Украина  
Дата: 15.06.08 10:52
Оценка:
Кто-нибудь можеть привести пример разумного применения?
Русский военный корабль идёт ко дну!
Re: Зачем существует std::multiset
От: Vain Россия google.ru
Дата: 15.06.08 12:32
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Кто-нибудь можеть привести пример разумного применения?

имххо, set и multiset это примерно тожесамое что map и multimap, только без значений value.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[2]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 15.06.08 12:50
Оценка:
Здравствуйте, Vain, Вы писали:

V>имххо, set и multiset это примерно тожесамое что map и multimap, только без значений value.


Для multimap вижу применение: привязывать к структурам числовые ключи и работать с диапазомами этих ключей методами lower_bound, upper_bound, equal_range. Просто связать ключи и значения — это скорее hash_map чем multimap.

Зачем может пригодиться multiset — не понимаю.
Русский военный корабль идёт ко дну!
Re[3]: Зачем существует std::multiset
От: Zigmar Израиль  
Дата: 15.06.08 15:14
Оценка:
Здравствуйте, Alexander G, Вы писали:
AG>Зачем может пригодиться multiset — не понимаю.

Задача: У Маши в корзине 4 яблока. Мама положила ей в корзинку еще 3 груши. Сколько фруктов в корзинке у Маши?
Решение:
enum Fruit{Apple, Pear, Kiwi};
struct Masha_t {
  std::multiset<Fruit> basket;
}Masha;

for(int i=0; i<4; ++i)
  Masha.basket.insert(Apple);

for(int i=0; i<3; ++i)
  Masha.basket.insert(Pear);

size_t answer = Masha.basket.size();

"To protect people you must slay people. To let people live you must let people die. This is the true teaching of the sword."
-Seijuro Hiko, "Rurouni Kensin"
Re[4]: Зачем существует std::multiset
От: Roman Odaisky Украина  
Дата: 15.06.08 16:46
Оценка:
Здравствуйте, Zigmar, Вы писали:

Z>Задача: У Маши в корзине 4 яблока. Мама положила ей в корзинку еще 3 груши. Сколько фруктов в корзинке у Маши?


Здесь нужен std::map<Fruit, std::size_t>, а не multiset.
До последнего не верил в пирамиду Лебедева.
Re[2]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 15.06.08 17:45
Оценка:
Здравствуйте, R.K., Вы писали:

RK>Возможно, для хранения частично упорядоченного множества. Например:

RK>
RK>struct stri_less
RK>    : public std::binary_function<std::string, std::string, bool>
RK>{
RK>    bool operator()(const std::string &a, const std::string &b)
RK>    { return _stricmp(a.c_str(), b.c_str()) < 0; }
RK>};

RK>std::multiset<std::string, stri_less> mset;
RK>mset.insert("case");
RK>mset.insert("Case");
RK>mset.insert("caesar");
RK>mset.insert("cASe");
RK>mset.insert("CasE");
RK>mset.insert("casual");

RK>mset.equal_range("case"); // интервал со всеми видами "case"
RK>


Похоже, но
1. Не понимаю зачем такое может понадобиться.
2. Тут лучше подходит unordered_mulitset/hash_multiset, а не multiset.
Русский военный корабль идёт ко дну!
Re[4]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 15.06.08 17:57
Оценка:
Здравствуйте, Zigmar, Вы писали:

Z>Здравствуйте, Alexander G, Вы писали:

AG>>Зачем может пригодиться multiset — не понимаю.

Z>Задача: У Маши в корзине 4 яблока. Мама положила ей в корзинку еще 3 груши. Сколько фруктов в корзинке у Маши?

Z>Решение:

Не очень убедительно. Для данной задачи будет лучше vector. Для оптимальой работы при большом количестве фруктов и малом количестве типов фуктов — вариант Roman Odaisky. При большом числе типов фуктов — unordered_multiset.
Русский военный корабль идёт ко дну!
Re[5]: Зачем существует std::multiset
От: Zigmar Израиль  
Дата: 15.06.08 22:18
Оценка:
Здравствуйте, Alexander G, Вы писали:
Z>>Задача: У Маши в корзине 4 яблока. Мама положила ей в корзинку еще 3 груши. Сколько фруктов в корзинке у Маши?
Z>>Решение:
AG>Не очень убедительно. Для данной задачи будет лучше vector. Для оптимальой работы при большом количестве фруктов и малом количестве типов фуктов — вариант Roman Odaisky. При большом числе типов фуктов — unordered_multiset.
Эты была скорее шутка На практике, я не разу не сталкивался с задачей, где мне пришлось пользоваться multiset. Но мне кажется, что такие случае вполне могут быть, как пример выше, когда предикат сравнения не гарантирует тождественности самих объектов.
"To protect people you must slay people. To let people live you must let people die. This is the true teaching of the sword."
-Seijuro Hiko, "Rurouni Kensin"
Re[3]: Зачем существует std::multiset
От: jazzer Россия Skype: enerjazzer
Дата: 16.06.08 01:20
Оценка:
Здравствуйте, Alexander G, Вы писали:

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


RK>>Возможно, для хранения частично упорядоченного множества. Например:

AG>2. Тут лучше подходит unordered_mulitset/hash_multiset, а не multiset.
Интересно, как unordered_mulitset может подойти лучше в задаче, в которой требуется упорядочение.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Зачем существует std::multiset
От: jazzer Россия Skype: enerjazzer
Дата: 16.06.08 01:22
Оценка:
Здравствуйте, Zigmar, Вы писали:

Z>Здравствуйте, Alexander G, Вы писали:

Z>>>Задача: У Маши в корзине 4 яблока. Мама положила ей в корзинку еще 3 груши. Сколько фруктов в корзинке у Маши?
Z>>>Решение:
AG>>Не очень убедительно. Для данной задачи будет лучше vector. Для оптимальой работы при большом количестве фруктов и малом количестве типов фуктов — вариант Roman Odaisky. При большом числе типов фуктов — unordered_multiset.
Z>Эты была скорее шутка На практике, я не разу не сталкивался с задачей, где мне пришлось пользоваться multiset. Но мне кажется, что такие случае вполне могут быть, как пример выше, когда предикат сравнения не гарантирует тождественности самих объектов.

Вообще-то предикаты, не гарантирующие тождественности, встречаются сплошь и рядом, а именно — когда ты упорядочиваешь структуры по одному полю и значения этого поля не являются уникальными (например, фамилия).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Зачем существует std::multiset
От: Cyberax Марс  
Дата: 16.06.08 01:36
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Кто-нибудь можеть привести пример разумного применения?

Да запросто. Например, у тебя у человека есть набор отработаных смен, и нужно их распределить по датам. std::map<date, shift> не пойдёт, так как могут быть две (или три) смены в один день. Тут-то std::multimap/multiset и помогает.
Sapienti sat!
Re: Зачем существует std::multiset
От: igna Россия  
Дата: 16.06.08 05:07
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Кто-нибудь можеть привести пример разумного применения?


Словарь, где словарные статьи отсортированы по алфавиту, а синонимы не объединены в одной статье.
Re: Зачем существует std::multiset
От: sokel Россия  
Дата: 16.06.08 10:17
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Кто-нибудь можеть привести пример разумного применения?


например, над множеством объектов требуется построить различные индексы по каким любо ключам.
как вариант, индексы можно делать в виде set или multiset из указателей с соответсвующими компараторами — multisetset<T*, T_compare>
Re[4]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 13:26
Оценка:
Здравствуйте, jazzer, Вы писали:

RK>>>Возможно, для хранения частично упорядоченного множества. Например:

AG>>2. Тут лучше подходит unordered_mulitset/hash_multiset, а не multiset.
J>Интересно, как unordered_mulitset может подойти лучше в задаче, в которой требуется упорядочение.

Интересно как в случае multiset (не multimap) извлечь пользу из упорядочения.
Русский военный корабль идёт ко дну!
Re[2]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 13:29
Оценка:
Здравствуйте, maq, Вы писали:

maq>Пример: есть заказ и его составляющие, т.е. отношение один ко многим.


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


Это multimap, а не multiset, причём скорее даже unordered_multimap
Русский военный корабль идёт ко дну!
Re[3]: Зачем существует std::multiset
От: maq Россия http://www.maqdev.com
Дата: 16.06.08 13:34
Оценка:
AG>Это multimap, а не multiset, причём скорее даже unordered_multimap

Ну не обязательно, ведь ID это значение поля класса, который будет лежать в multiset, зачем его еще как ключ выносить в map.
Re[2]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 13:39
Оценка:
Здравствуйте, sokel, Вы писали:

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

S>как вариант, индексы можно делать в виде set или multiset из указателей с соответсвующими компараторами — multisetset<T*, T_compare>

Допустим имеем такой multiset (пишу прямо сюда, может не скомпилиться, но думаю код понятен):

struct T { int a, b, c, d, e };

strunct T_compare
  : public std::binary_function<T*, T*, bool>
{
  T_compare(void) : f_(boost::bind(T::d, _1) < boost::bind(T::d, _2)) {}
  bool operator()(T* lhs, T*, rhs) { return f_(lhs, rhs); }
private:
  boost::function<bool (T*, T*)> f_;
}

multisetset<T*, T_compare>


Ну вот он упорядочен по d. Дальше что ? Чтобы работать теперь с диапазонами, нужны не ключи, а сами T*. Вряд ли это полезно.
Русский военный корабль идёт ко дну!
Re[2]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 13:41
Оценка:
Здравствуйте, igna, Вы писали:

I>Словарь, где словарные статьи отсортированы по алфавиту, а синонимы не объединены в одной статье.


И зачем в словаре сортировать слова по алфавиту, если unordered_multiset вроде как быстрее ?
Русский военный корабль идёт ко дну!
Re[2]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 13:42
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Да запросто. Например, у тебя у человека есть набор отработаных смен, и нужно их распределить по датам. std::map<date, shift> не пойдёт, так как могут быть две (или три) смены в один день. Тут-то std::multimap/multiset и помогает.


multimap — да, насколько я понимаю, именно для этого. но multiset — ?
Русский военный корабль идёт ко дну!
Re[4]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 13:54
Оценка:
Здравствуйте, maq, Вы писали:

maq>Ну не обязательно, ведь ID это значение поля класса, который будет лежать в multiset, зачем его еще как ключ выносить в map.


Затем, чтобы значение ID можно было передать в eqaul_range.
Русский военный корабль идёт ко дну!
Re[5]: Зачем существует std::multiset
От: jazzer Россия Skype: enerjazzer
Дата: 16.06.08 14:05
Оценка:
Здравствуйте, Alexander G, Вы писали:

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


RK>>>>Возможно, для хранения частично упорядоченного множества. Например:

AG>>>2. Тут лучше подходит unordered_mulitset/hash_multiset, а не multiset.
J>>Интересно, как unordered_mulitset может подойти лучше в задаче, в которой требуется упорядочение.

AG>Интересно как в случае multiset (не multimap) извлечь пользу из упорядочения.


очередь сообщений, упорядоченная по таймстемпу с плохим разрешением
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 14:24
Оценка:
Здравствуйте, jazzer, Вы писали:

J>очередь сообщений, упорядоченная по таймстемпу с плохим разрешением


Это priority_queue, нет ?
Русский военный корабль идёт ко дну!
Re[3]: Зачем существует std::multiset
От: igna Россия  
Дата: 16.06.08 14:44
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>И зачем в словаре сортировать слова по алфавиту, если unordered_multiset вроде как быстрее ?


Чтобы имитировать привычный пользователю просмотр книжного словаря.
Re[3]: Зачем существует std::multiset
От: Кодт Россия  
Дата: 16.06.08 14:55
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>2. Тут лучше подходит unordered_mulitset/hash_multiset, а не multiset.


1) unordered_* и hash_* есть в STL?
2) какая временная сложность у unordered_multiset?
3) как по заданному предикату сравнения (равенства или порядка, неважно) сделать хеш-функцию?

Например, есть функция strcoll, сравнивающая строки в соответствие с текущей (или заданной) локалью.
Я надеюсь, что она корректно обрабатывает лигатуры, умляуты и т.п.
То есть, немецкие слова Roentgen и Röntgen попадут в одну корзину.

Хеш-функция, читающая строку посимвольно, даст разные значения для слитного и раздельного написания умляута. Получится более сильный предикат, чем искомый — а должен быть более слабый.
Значит, нам нужна хеш-функция, читающая строку порциями, да ещё в зависимости от локали.
Давайте попросим разработчиков ОС и компиляторов, чтоб они включили эти хеш-функции в соответствующие системные библиотеки? Дело-то хорошее...
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[4]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 15:18
Оценка:
Здравствуйте, igna, Вы писали:

I>Чтобы имитировать привычный пользователю просмотр книжного словаря.


Для пользователя нам надо отображать не всё — всё на экране не поместится.
Значит нужен random access iterator, к которому прибавляется положение скроллбара. Это сортированный vector.
Русский военный корабль идёт ко дну!
Re[5]: Зачем существует std::multiset
От: igna Россия  
Дата: 16.06.08 15:34
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Для пользователя нам надо отображать не всё — всё на экране не поместится.

AG>Значит нужен random access iterator, к которому прибавляется положение скроллбара. Это сортированный vector.

Я видел такой скроллбар для просмотра словаря из более чем ста тысяч слов. Использовать его двигая вверх-вниз мышью было довольно неудобно и бессмысленно, все равно не знаешь куда попадешь (хуже чем в книжном словаре). Реально пользователям это было не нужно, они просто хотели видеть слова предшествующие или последующие найденному поиском слову. Для такой функциональности сортированный вектор не нужен, но сортировка все-таки нужна.
Re[6]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 16.06.08 15:42
Оценка:
Здравствуйте, igna, Вы писали:

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


Хорошо, без скролбара. Хотя скролбаром нужно просто уметь пользоваться — двигать ползунок, затем кликать мжду ползунком и стрелкой, затем кликать по стрелке — вот в такой последовательности точность будет повышаться. А ещё есть клавиши управления курсором.

Всё равно, если пользователь не добавляет слова то лучше вектор.
А если даже взять словарь, где пользователь добавляет слова, нужен mulitmap, а не multiset, потому что у слов есть значения.
Русский военный корабль идёт ко дну!
Re[7]: Зачем существует std::multiset
От: igna Россия  
Дата: 16.06.08 15:59
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Хорошо, без скролбара. Хотя скролбаром нужно просто уметь пользоваться — двигать ползунок, затем кликать мжду ползунком и стрелкой, затем кликать по стрелке — вот в такой последовательности точность будет повышаться. А ещё есть клавиши управления курсором.


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

AG>Всё равно, если пользователь не добавляет слова то лучше вектор.


Почему?
Re[9]: Зачем существует std::multiset
От: Юрий Жмеренецкий ICQ 380412032
Дата: 16.06.08 17:36
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>А чем multiset::equal_range лучше std::equal_range ?

Теоритически может быть быстрее, если реализована не дословно как 'make_pair(a.lower_bound(k), a.upper_bound(k))', а с использованием некоторых деталей реализации.

AG>std::vector — дефолтный контейнер, это использование других вместо него нужно обосновывать.

+1
Re[3]: Зачем существует std::multiset
От: sokel Россия  
Дата: 16.06.08 18:13
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Ну вот он упорядочен по d. Дальше что ? Чтобы работать теперь с диапазонами, нужны не ключи, а сами T*. Вряд ли это полезно.


И всё-таки, может быть полезно. Если, например, в сравнении участвует множество полей структуры. Плюс в разных индексах сравниваемые наборы полей могут пересекаться. И в отдельную структуры-ключи выносить не хочется. Для поиска создаем объект на стеке, в нем заполняем нужные для компаратора поля и вперед — получать диапазоны.

P.S. эти проблемы решаются с помощью multiindex вроде, но для себя все вопросы с ассоциативными контейнерами давно решил велосипедом. самодельное дерево + стратегия доступа к линкам в объектах (объекты сами по себе являются нодами). а для порядка — отдельная стратегия (нужна в insert-erase). деревья с фиксированными стратегиями порядка — аналоги stl деревьев. ну и по сути все деревья тогда представляются как своеобразный set или multiset. разница только в стратегиях порядка, определяющих варианты сравнения объектов с ключами (и/или с самим собой) и возможность множественной вставки. это могут быть стратегии упорядовачивания по member-ключу, типа member_order (кстати, можно даже мутить стратегии, которые будут принимать на вход тип ключа, вообще не имеющий отношения к объектам, например поиск по паре типа std::pair а порядок при вставке просто по паре членов структуры, просто чуть сложней стратегия (реализовать сравнение во всех вариантах типа объекта и типа ключа, соответственно стратегии вроде pair-triple-quad-member_order). различные варианты self_order стратегий (как для set). довольно часто попадаются стратегии навроде cast_member_order — по члену предка или потомка при возможности static_cast.
Re[6]: Зачем существует std::multiset
От: Erop Россия  
Дата: 16.06.08 18:24
Оценка:
Здравствуйте, igna, Вы писали:

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


1) Советую посмотреть, например, как работает скроллер в лингво.
2) Жизнь такова, что обычно словарей много, а пользователю надо показывать их слияние...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Зачем существует std::multiset
От: igna Россия  
Дата: 17.06.08 05:30
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>std::vector — дефолтный контейнер, это использование других вместо него нужно обосновывать.


Хорошо, согласен.

AG>А если даже взять словарь, где пользователь добавляет слова, нужен mulitmap, а не multiset, потому что у слов есть значения.


А вот этот аргумент не понял. У слов есть значения? Можно и под этим углом посмотреть, но зачем? Например пользователь создает новую статью, и часть программы отвечающая за создание объекта Статья знает, что две части этого объекта будут храниться отдельно? Или она этого не знает, и созданный ей объект преобразуется затем к виду подходящему для хранения в multimap?
Re[7]: Зачем существует std::multiset
От: igna Россия  
Дата: 17.06.08 05:35
Оценка:
Здравствуйте, Erop, Вы писали:

E>1) Советую посмотреть, например, как работает скроллер в лингво.


Спасибо за совет, а на что обратить внимание?

E>2) Жизнь такова, что обычно словарей много, а пользователю надо показывать их слияние...


Можно поподробнее? Это аргумент за или против multiset?
Re[5]: Зачем существует std::multiset
От: maq Россия http://www.maqdev.com
Дата: 17.06.08 09:46
Оценка:
AG>Затем, чтобы значение ID можно было передать в eqaul_range.

В целом согласен, хотя это и не обязательно. В equal_range, или multiset:equal_range можно передать класс с инициализированным полем ID.
Re[8]: Зачем существует std::multiset
От: Erop Россия  
Дата: 17.06.08 10:06
Оценка:
Здравствуйте, igna, Вы писали:

I>Спасибо за совет, а на что обратить внимание?

Ну подёргай его, понажимай в разные места и посмотри куда попадаешь. Узнаешь много нового. Так же, кстати, и другие словари читят.
Например, популярная темя -- попадать по движению очень длинного скроллера не в любую точку, а в границу логического контекста.

E>>2) Жизнь такова, что обычно словарей много, а пользователю надо показывать их слияние...

I>Можно поподробнее? Это аргумент за или против multiset?
Ну не годятся стандартные контейнеры в электронных словарях. Так как тебе надо не вычитывая весь словарь с диска достать из него толкьо кусок, идущий подряд. При этом надо не из одного словаря, а из коллекции и всё это смёржить.
Посомтри, как какой-нибудь e-словарь (например Лингво) работает?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 17.06.08 10:46
Оценка:
Здравствуйте, igna, Вы писали:

I>А вот этот аргумент не понял. У слов есть значения? Можно и под этим углом посмотреть, но зачем? Например пользователь создает новую статью, и часть программы отвечающая за создание объекта Статья знает, что две части этого объекта будут храниться отдельно? Или она этого не знает, и созданный ей объект преобразуется затем к виду подходящему для хранения в multimap?


В любом случае, если у слов есть значения, нужен multimap, а не multiset. Что будет значением multimap это уже другой вопрос.
Если значений нет (орфографический словарь) то нужен set.
Русский военный корабль идёт ко дну!
Re[11]: Зачем существует std::multiset
От: igna Россия  
Дата: 17.06.08 11:19
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>В любом случае, если у слов есть значения, нужен multimap, а не multiset.


Чем multiset хуже?
Re[9]: Зачем существует std::multiset
От: igna Россия  
Дата: 17.06.08 11:46
Оценка:
Здравствуйте, Erop, Вы писали:

E>Ну не годятся стандартные контейнеры в электронных словарях.


Словарь-то не обязательно должен быть огромным. Представь изначально пустой словарь, заполняемый школьником изучающим иностранный язык. В нем будет максимум несколько тысяч слов.
Re[12]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 17.06.08 12:51
Оценка:
Здравствуйте, igna, Вы писали:

I>Чем multiset хуже?


Вот кстати этим


multiset: The key value of an element in a multiset may not be changed directly.
multimap: The value of an element in a multimap, but not its associated key value, may be changed directly.

Русский военный корабль идёт ко дну!
Re[13]: Зачем существует std::multiset
От: igna Россия  
Дата: 17.06.08 13:53
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Тем, что в его find, upper_bound, и другие нужно передавать то же, что хранится в нём, т.е. слово со значением.


Строго говоря, это неверно, поскольку можно передавать dummy-значение (а не то значение, "что хранится"), но понятно, что имеется ввиду. Аргумент принят.
Re[3]: Зачем существует std::multiset
От: sokel Россия  
Дата: 17.06.08 15:30
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Ну вот он упорядочен по d. Дальше что ? Чтобы работать теперь с диапазонами, нужны не ключи, а сами T*. Вряд ли это полезно.


такой вот несколько надуманный пример структуры с поиском по паре ключей:

#include <stdio.h>
#include <set>

struct s;
struct x_cmp { bool operator()(const s* s1, const s* s2) const; };
struct y_cmp { bool operator()(const s* s1, const s* s2) const; };

typedef std::multiset<s*, x_cmp> x_idx_type;
typedef std::multiset<s*, y_cmp> y_idx_type;
typedef x_idx_type::iterator x_iterator;
typedef y_idx_type::iterator y_iterator;

struct s
{
    s(int x, int y) : x(x), y(y) {}
    int x;
    int y;
    x_iterator x_it;
    y_iterator y_it;
};
bool x_cmp::operator()(const s* s1, const s* s2) const { return s1->x<s2->x; } 
bool y_cmp::operator()(const s* s1, const s* s2) const { return s1->y<s2->y; }

int main()
{
    x_idx_type    x_idx;
    y_idx_type    y_idx;
    for(int x=0;x<4;++x)
    {
        for(int y=0;y<4;++y)
        {
            s* ps = new s(x,y);
            ps->x_it = x_idx.insert(ps);
            ps->y_it = y_idx.insert(ps);
        }
    }
    for(x_iterator it=x_idx.begin();it!=x_idx.end();++it) printf("%d,%d;", (*it)->x, (*it)->y); printf("\n");
    // удалить все, для которых y = 2
    s key(0,2);
    std::pair<y_iterator, y_iterator> y_range = y_idx.equal_range(&key);
    y_iterator y_it = y_range.first;
    while(y_it!=y_range.second)
    {
        s* ps = *y_it;
        x_idx.erase(ps->x_it);
        y_idx.erase(y_it++);
        delete ps;
    }
    for(x_iterator it=x_idx.begin();it!=x_idx.end();++it) printf("%d,%d;", (*it)->x, (*it)->y); printf("\n");
    return 0;
}
Re[10]: Зачем существует std::multiset
От: Erop Россия  
Дата: 18.06.08 06:04
Оценка:
Здравствуйте, igna, Вы писали:

I>Словарь-то не обязательно должен быть огромным. Представь изначально пустой словарь, заполняемый школьником изучающим иностранный язык. В нем будет максимум несколько тысяч слов.

Известные мне электронные словари расчитаны на возможноть подключения очень больших словарей.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Зачем существует std::multiset
От: Аноним  
Дата: 19.06.08 07:49
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Кто-нибудь можеть привести пример разумного применения?


//Все очень просто 
//multiset может хотябы пригодится для случаев когда он хранит класс 
//для которого перегружен оператор меньше таким образом что сравнивается одно поле
//а второе поле игнорируется но при этом вторые поля у сравниваемых объектов могут отличаться
//здесь собсвтенно мультисет и может пригодится 
//как пример 
#include <iostream>
#include <string>
#include <set>
#include <iterator>
struct asc{ 
 int key;
 std::string value;
 asc( int k, std::string v ) : key(k),value(v) { } 
 asc( ) {} 
 bool operator < ( const asc &object ) const { 
  return key < object.key;
 } 
};

int main() { 
 std::set< asc > so;
 std::multiset< asc > sm;
 
 so.insert( asc( 1, "before" ) );
 so.insert( asc( 1, "after" ) );

 sm.insert( asc( 1, "before" ) );
 sm.insert( asc( 1, "after" ) );
 
 std::cout << "so size = " << so.size() << std::endl; //здесь мы потеряем значение
 std::cout << "sm size = " << sm.size() << std::endl; //здесь все в порядке
}
Re[2]: Зачем существует std::multiset
От: Alexander G Украина  
Дата: 19.06.08 08:14
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
А>//Все очень просто 
А>//multiset может хотябы пригодится для случаев когда он хранит класс 
А>//для которого перегружен оператор меньше таким образом что сравнивается одно поле
А>//а второе поле игнорируется но при этом вторые поля у сравниваемых объектов могут отличаться
А>//здесь собсвтенно мультисет и может пригодится 
А>


Я понимаю что это будет работать, но это хуже multimap, т.к. :
Не забывайте также, что для просто key-value лучше подходят хеш-таблицы. Упорядоченное по ключу множество нужно тогда, когда требуется порядок элементов.

Всё это вместе приводит к тому, что я не могу придумать случая, когда multiset был бы правильным выбором контейнера.
Русский военный корабль идёт ко дну!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.