Название: Слияние 2 сортированных контейнеров Отправлено: Igors от Июль 31, 2014, 15:52 Добрый день
Делаю интерактивный редактор типа "кисти" которая красит точки на "холсте" (в терминах Верес(а)) :). Возникла такая задачка: даны 2 контейнера структур сортированных по возрастанию Код Гарантируется уникальность first (ключа) в обоих исходных. В первом все second (значения) ненулевые. Нужно получить контейнер также сортированный, Код правила - если значение = 0 во втором контейнере, такой эл-т не включается в выходной (хоть и был с таким ключом в первом). Др словами это операция удаления - если эл-т с одним и тем же ключом есть в обоих - то принимается значение из второго (операция замещения) и эл-т включается в выходной - если эл-т с таким ключом (и ненулевым значением) только в первом или только во втором - он включается в выходной со своим значением. "Простые" решения (напр с сортировкой) неприемлемы по скорости. Ну что, есть возможность блеснуть техникой, навернуть крутейшие лямбды и.т.п. Прошу :) ------ Edit: еще лучше не возвращать контейнер, а модифицировать первый Код Первый - исходные данные (потенциально большие), второй - что юзер натюкал мышей. Часто второй всего неск значений (а то и одно), поэтому хотелось бы отделаться только изменениями в первом (если такая возможность есть). Ну ладно, то "optional", реализация первоначального тоже интересна Название: Re: Слияние 2 сортированных контейнеров Отправлено: m_ax от Июль 31, 2014, 18:56 Набросал на коленке (немного изменённый std::merge..)
Код
Не проверял, но идея, думаю, понятна.. Название: Re: Слияние 2 сортированных контейнеров Отправлено: Igors от Июль 31, 2014, 19:48 Проверяем кончился ли один из контейнеров, если да - копируем хвост второго. Хорошо, а дальше
Код
Первый: (1, 0.6) (2, 0.1) ... Второй: (2, 0.0) ... В итоге эл-т (2, 0.1) успешно проскочил (а не должен был) Название: Re: Слияние 2 сортированных контейнеров Отправлено: m_ax от Июль 31, 2014, 20:07 Цитировать В итоге эл-т (2, 0.1) успешно проскочил (а не должен был) Не страшно) Есть предикат, а его уже можно научить и это проверять) Название: Re: Слияние 2 сортированных контейнеров Отправлено: Igors от Август 01, 2014, 10:21 Не страшно) Есть предикат, а его уже можно научить и это проверять) А можно увидеть процесс его обучения? :) Ведь сейчас до нужного ф-ционала еще далекоНазвание: Re: Слияние 2 сортированных контейнеров Отправлено: Bepec от Август 01, 2014, 10:40 offtop: Объяснив с "моей" терминологией вы четко обрисовали задачу. Однако, это уже прогресс :)
Название: Re: Слияние 2 сортированных контейнеров Отправлено: m_ax от Август 01, 2014, 10:50 Не страшно) Есть предикат, а его уже можно научить и это проверять) А можно увидеть процесс его обучения? :) Ведь сейчас до нужного ф-ционала еще далекоОй далекоооо) Ну, например, как то так (не проверял: это уже вопрос десятый, главное идея..): Код
Название: Re: Слияние 2 сортированных контейнеров Отправлено: Igors от Август 01, 2014, 10:51 Вот картинка чтобы оживить обсуждение. Точки (узлы сетки) хранятся как пары *индекс + значение" которое показано цветом. Черные точки не хранятся (background). Юзер тыкает "кистью" которая может быть достаточно большой. Если кисть "жесткая" то все точки попавшие в радиус захвата получают цвет кисти (или удаляются из контейнера если кисть черная). Если кисть "мягкая" то результат размазывается/интерполируется от центра к краю. Формализуя это приходим к правилам поста #1
Название: Re: Слияние 2 сортированных контейнеров Отправлено: Igors от Август 02, 2014, 11:34 Код
Название: Re: Слияние 2 сортированных контейнеров Отправлено: m_ax от Август 02, 2014, 12:27 Цитировать Пример: второй контейнер (1, 0) (2, 0)... эл-т с индексом 1 не будет удален (из первого) Пфф.. Если нужна предыстория по всем нулевым ключам, то можно заменить boost::optional на обычный set, например. Код
Но это всё детали конкретной реализации Вашего steppera. Основная здесь мысль в том, что этот подход сейчас достаточно гибок. Если завтра Вам придёт в голову написать ещё десяток правил для слияния, то достаточно лишь написать свои пользовательские stepperы при этом ничего не меняя в самой функции merge_if. Более того, она будет работать с любым контейнером.. Название: Re: Слияние 2 сортированных контейнеров Отправлено: Igors от Август 02, 2014, 14:20 Пфф.. Если нужна предыстория по всем нулевым ключам, то можно заменить boost::optional на обычный set, например. Что значит "Пфф.. если нужна"? Не надо мне одолжений делать, условия знаете - стало быть нужна. И чего вот так, без раздумий, тулить ассоциативный контейнер? Это удовольствие дорогое. Не лучше ли такКод Но это неоптимально. Пример: юзер выбрал всего одну точку и меняет ее значение напр с 0.1 на 0.5. Чего же перемалывать весь контейнер? Ведь он сортирован, возможно пресловутое log(N). Как это сделать не плодя частных случаев? Название: Re: Слияние 2 сортированных контейнеров Отправлено: Bepec от Август 02, 2014, 15:17 Без частных случаев - перемалывать весь контейнер :D
Название: Re: Слияние 2 сортированных контейнеров Отправлено: m_ax от Август 02, 2014, 15:27 Цитировать Пример: юзер выбрал всего одну точку и меняет ее значение напр с 0.1 на 0.5. Чего же перемалывать весь контейнер? Ведь он сортирован, возможно пресловутое log(N). Как это сделать не плодя частных случаев? Не понял? Есть два контейнера, нужно слить их в третий.. Это уже как минимум ~ N.. О каком логарифме идёт речь? Название: Re: Слияние 2 сортированных контейнеров Отправлено: Igors от Август 03, 2014, 09:00 Не понял? Есть два контейнера, нужно слить их в третий.. Это уже как минимум ~ N.. О каком логарифме идёт речь? Edit: еще лучше не возвращать контейнер, а модифицировать первый Код Первый - исходные данные (потенциально большие), второй - что юзер натюкал мышей. Часто второй всего неск значений (а то и одно), поэтому хотелось бы отделаться только изменениями в первом (если такая возможность есть). Название: Re: Слияние 2 сортированных контейнеров Отправлено: m_ax от Август 04, 2014, 11:27 Цитировать Первый - исходные данные (потенциально большие), второй - что юзер натюкал мышей. Часто второй всего неск значений (а то и одно), поэтому хотелось бы отделаться только изменениями в первом (если такая возможность есть). Хотите быстрый поиск (logN), придётся использовать контейнер с random access доступом.. Но, вот если юзер тыкнет мышью и изменит значение на 0.0, то затраты на "выковыривание" этой точки из первого контейнера (вектора) перекроют затраты на поиск.. Короче, оно того стоит? Название: Re: Слияние 2 сортированных контейнеров Отправлено: Igors от Август 04, 2014, 12:50 Но, вот если юзер тыкнет мышью и изменит значение на 0.0, то затраты на "выковыривание" этой точки из первого контейнера (вектора) перекроют затраты на поиск.. С одной точкой все прекрасно получается в общем виде. Все равно чтобы "выковырять" ее надо сначала найти.Хотите быстрый поиск (logN), придётся использовать контейнер с random access доступом.. Короче, оно того стоит? Насколько я помню random access означает просто одинаковое время доступа к эл-ту, массив этому требованию удовлетворяет. Вероятно Вы имели ввиду ассоциативный контейнер, напр std::map/set. С таким конечно думать не надо, все операции очевидны (за что придется заплатить перегонками в др местах кода). И так ли уж это хорошо? Напр при большом кол-ве удаляемых std::set легко может оказаться медленнее. Вообще чем сортированный массив хуже? Тем что накладно вставлять/удалять? Так здесь это в одной интерактивной операции, не страшно. Что тут сложного/военного? Только то что никогда раньше это не делали :)Название: Re: Слияние 2 сортированных контейнеров Отправлено: m_ax от Август 04, 2014, 13:36 Цитировать Насколько я помню random access означает просто одинаковое время доступа к эл-ту, массив этому требованию удовлетворяет. Вероятно Вы имели ввиду ассоциативный контейнер, напр std::map/set. С таким конечно думать не надо, все операции очевидны (за что придется заплатить перегонками в др местах кода). И так ли уж это хорошо? Напр при большом кол-ве удаляемых std::set легко может оказаться медленнее. Вообще чем сортированный массив хуже? Тем что накладно вставлять/удалять? Так здесь это в одной интерактивной операции, не страшно. Что тут сложного/военного? Только то что никогда раньше это не делали random access - это фактически доступ по индексу за константное время (например вектор). Например в списке, даже сортированном, поиск будет "линейным", а не "логарифмическим", но.. Я хотел сказать, что если подразумевается возможное удаление, вставка элементов, то для вектора, даже с логарифмическим поиском, это будет затратнее в целом, чем, например, с тем же списком, хоть и с линейным поиском. Вообщем, все эти пляски с частными случаями и оптимизацией сейчас напоминают миф о Сизифе.. Может имеет смысл/правильнее вернуться назад и пересмотреть архитектурно те решения, которые привели к этой задаче?) Название: Re: Слияние 2 сортированных контейнеров Отправлено: Igors от Август 04, 2014, 14:28 Вообщем, все эти пляски с частными случаями и оптимизацией сейчас напоминают миф о Сизифе.. К чему сводится этот "архитектурный пересмотр"? Давайте возьмем более подходящий контейнер (напр std::set). Это понятно, но не всегда удобно/выгодно. Есть др модули для которых текущий формат данных утвержден (кстати он такой же и в др приложениях), а гонять из одного контейнера в другой не есть хорошо. Кроме того, прикинув возможные варианты, легко убедиться что шаблонное решение std::set оптимальным совсем не является. Вот были бы данные не сортированы - тогда да, а так нет.Может имеет смысл/правильнее вернуться назад и пересмотреть архитектурно те решения, которые привели к этой задаче?) Меня вполне устраивает слияние в выходной контейнер (как обсуждалось выше), но интересна общая ситуация. Фактически есть сортированный контейнер (первый) и набор команд (типа batch) - второй контейнер. Набор полный: изменить/добавить/удалить. Как его оптимально "процессить"? |