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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> list + уникальные элементы + сортировка, сортировка меняется на ходу 
V
    Опции темы
asmdzen
Дата 26.6.2011, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



**


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

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



Нужен контейнер с уникальными элементами как в map'е но с возможностью применять сортировку по разным принципам в разное время.
например у меня есть структура типа
Код

struct user{
    int id;
    DWORD ip;
    int input_count;
}
 
нужна возможность указать контейнеру таких структур или указателей на них отсортировать весь контейнер по определенному элементу структуры (ip, input_count), при добавлении новых элементов они уже будут сортироваться по новому принципу.
что у меня получилось:
 
Код

template <typename T1, typename T2>
class uniqList : public std::list<T2>
{
private:
    typedef std::set<T1> keys_set;
    typedef std::list<T2> list_type;
    keys_set keys;

    typename list_type::iterator insert ( typename std::list<T2>::iterator position, const T2& x );
    void insert ( typename list_type::iterator position, size_t n, const T2& x );
    template <class InputIterator>
    void insert ( typename list_type::iterator position, InputIterator first, InputIterator last );
    void push_front ( const T2& x );
    void push_back ( const T2& x );

    class eq
    {
    private:
        T2 x;
    public:
        eq(T2 init): x(init) {}
        bool operator () ( const T2 &x2 ) {
            return x2 > x;
        }
    };

public:
    typename std::pair<typename list_type::iterator, bool> insert ( const T1 key, const T2& x ) {
        bool found = !keys_set.insert(key).second;

        if(!found) {// add to list
            // add sorted to list
        } else { // found return iterator pointed to it
            return make_pair(find_if( list_type::begin(), list_type::end(), eq(x)), false);
        }
    }

};

как организовать сортировку по определенному принципу непонятно, может есть какое-то стандартное решение или кто-то с этим уже работал?

Добавлено через 11 минут и 45 секунд
приходит на ум только изменять поведение "operator'а <" в структуре, вызывать сорт для пересортировки, новые элементы уже будут добавятся на основании этих изменений.
при добавлении нового элемента - ищем первый элемент больший нужного нам, вставляем перед ним.

Это сообщение отредактировал(а) asmdzen - 26.6.2011, 23:17
PM MAIL   Вверх
afiskon
Дата 27.6.2011, 06:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 31.3.2011
Где: Россия, Москва

Репутация: 1
Всего: 4



Используйте несколько map'ов или set'ов для сортировки по каждому ключу.
PM MAIL WWW   Вверх
Earnest
Дата 27.6.2011, 08:28 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



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


--------------------
...
PM   Вверх
Сыроежка
Дата 28.6.2011, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(asmdzen @  26.6.2011,  23:09 Найти цитируемый пост)
   class eq
    {
    private:
        T2 x;
    public:
        eq(T2 init): x(init) {}
        bool operator () ( const T2 &x2 ) {
            return x2 > x;
        }
    };


Почему вы у опреатора функции не указали квалификатор const?

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

Как я понял, вы используете контейнер std::set лишь для проверки уникальности элементов в контейнере std::list.

Вам фактически нужно соритровать лишь список. Какие в связи с этим вопросы? Если я не ошибаюсь (под рукой нет шпаргалки), то контейнер std::list имеет функции-члены сортировки. В крайнем случае вы можете воспользоваться стандартным алгоритмом сортировки std::sort. Как задать различные условия? Используете алгоритм сортировки с предикатом, где в качестве предиката указывайте любые условия, какие вам придут в голову. Вы же уже умеете писать оператор функцию. Фактически, предикат и составляет оператор функцию, либо непосредственно можете указывать различные функции члена класса, содержащие требуемые условия. 

При сортировке вам в вашу функцию будут передаваться два элемента вашего класса. Вы можете сравнивать любые их поля.

То есть вы для своего класса пишите функцию-обертку либо для встроенной сортировки в контейнере list либо для стандартного алгоритма std::sort. Ее шаблон копируете на основе стандартного шаблона функции сортировки. Шаблонным типом будет лишь только предикат

Примерно так (без всяой проверки):


Код

template <typename T1, typename T2>
class uniqList : public std::list<T2>
{

template <typename BinaryPredicate>
void sort( BinaryPredicate binary_predicate )
{
// А здесь вызываете стандартную функцию сортировки с итераторами для вашего списка
// Например, если использовать стандартный алгоритм sort

std::sort( begin(), end(), binary_predicate );
}

PM MAIL   Вверх
volatile
Дата 29.6.2011, 01:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 37
Всего: 85



Цитата(Сыроежка @  28.6.2011,  19:18 Найти цитируемый пост)
std::sort( begin(), end(), binary_predicate );

для алгоритма std::sort необходим контейнер с произвольным доступом.
ни std::list, ни тем более наследник от std::list таким не является.

asmdzen, воспользуйтесь советом от Earnest
Это реально рабочий и наиболее эффективный способ.


Это сообщение отредактировал(а) volatile - 29.6.2011, 01:52
PM MAIL   Вверх
Earnest
Дата 29.6.2011, 10:09 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(volatile @  29.6.2011,  02:50 Найти цитируемый пост)
ни std::list, ни тем более наследник от std::list таким не является.

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


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



**


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

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



Цитата(Earnest @  27.6.2011,  08:28 Найти цитируемый пост)
Основной контейнер самого простого типа, какой позволяет задача (вектор или список), для хранения элементов, + сколько надо индексов, которые сортируют указатели. 

а уникальность? не хочется после каждого insert делать sort (сейчас так работает), думаю более подходящим для меня является именно то что показал Сыроежка, у list'а есть собственный sort, который может сортировать по operator < или по объекту comparator'у. Всем спасибо за помошь.

П.С.
Цитата(Сыроежка @  28.6.2011,  19:18 Найти цитируемый пост)
Почему вы у опреатора функции не указали квалификатор const?

не балуюсь такими ограничителями )

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


Эксперт
****


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

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



Цитата(asmdzen @  29.6.2011,  13:20 Найти цитируемый пост)
не хочется после каждого insert делать sort

Цитата(asmdzen @  29.6.2011,  13:20 Найти цитируемый пост)
у list'а есть собственный sort, который может сортировать по operator <

какая разница ?

Если список в каждый момент времени уже отсортирован, можно либо ручками, либо каким-нибудь std::merge вставлять элемент в "своё" место. По идее это будет занимать log2(N) операций.

Цитата(asmdzen @  29.6.2011,  13:20 Найти цитируемый пост)
не балуюсь такими ограничителями )

зря, батенька, зря © самизнаетекто


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



**


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

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



Цитата(borisbn @  29.6.2011,  18:07 Найти цитируемый пост)
std::merge
 спасибо, я об этом не подумал, хотя наверное посмотрю как он работает и прикручу свой, не брать ведь для этого еще один list.

Цитата(borisbn @  29.6.2011,  18:07 Найти цитируемый пост)
Цитата(asmdzen @  29.6.2011,  13:20 Найти цитируемый пост)
не хочется после каждого insert делать sort

Цитата(asmdzen @  29.6.2011,  13:20 Найти цитируемый пост)
у list'а есть собственный sort, который может сортировать по operator <

какая разница ?

сами ведь merge предложили ) т.е. sort я конечно сделаю но только после подмены operator'а <, а для обычной вставки уже merge.

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


Эксперт
****


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

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



Цитата(asmdzen @  29.6.2011,  18:19 Найти цитируемый пост)
хотя наверное посмотрю как он работает и прикручу свой

не люблю велосипедов, но в данном случае, думаю, ты прав: у merge интерфейс совершенно не удобный для твоей задачи


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


Шустрый
*


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

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



Вообще-то, на мой взгляд правильнее было бы делать не производный класс от std::list, а сделать  std::list членом вашего класса точно также, как вы сделали членом класса std::map.

Это сообщение отредактировал(а) Сыроежка - 29.6.2011, 19:12
PM MAIL   Вверх
asmdzen
Дата 29.6.2011, 19:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



**


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

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



Цитата(Сыроежка @  29.6.2011,  19:12 Найти цитируемый пост)
std::map
 std::set?
не хочется еще тысячу методов добавлять, просто убрал мешающие и все, пускай все остальные методы list'a останутся (не разобрался еще какие нужны, какие нет).
было бы просто замечательно если можно было бы работать с полями структур, или просто указывать контейнеру из хранимого элемента какая часть является идентификатором(id) определяющий уникальность элементов и указывать по какой части сортировать элементы.

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

void myStructIdComparator(const mystructT& rhs, int& id, int& comparator);

в общем идея была не плоха (
понятия не имею как это реализовать, подумаю еще.
PM MAIL   Вверх
borisbn
Дата 29.6.2011, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Сыроежка @  29.6.2011,  19:12 Найти цитируемый пост)
Вообще-то, на мой взгляд правильнее было бы делать не производный класс от std::list, а сделать  std::list членом вашего класса точно также, как вы сделали членом класса std::map.

кста, уже обсуждали и довольно подробно




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



**


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

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



borisbn, ну не знаю, вроде правильно наследую, мне ведь нужно еще один контейнер прикрепить, да и передавать этот новый контейнер потом можно как std::list.
а если подумать то получается std::map с возможностью sort'а (автоматического в том числе), поищу может найду что-то подобное.
PM MAIL   Вверх
spyswamp
Дата 8.7.2011, 13:42 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 1
Всего: 7



Цитата(Earnest @ 27.6.2011,  08:28)
Основной контейнер самого простого типа, какой позволяет задача (вектор или список), для хранения элементов, + сколько надо индексов, которые сортируют указатели.

Для этого уже придумали boost::multi_index::multi_index_container. Не надо изобретать велосипеды. smile


--------------------
- why you call it beta?
- cuz it's betta then nothin'
PM MAIL   Вверх
baldina
Дата 8.7.2011, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



если boost кажется тяжелым, 
Цитата(Earnest @  27.6.2011,  08:28 Найти цитируемый пост)
сколько надо индексов
 - самое оно

PM MAIL   Вверх
spyswamp
Дата 11.7.2011, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 1
Всего: 7



baldina, а чего там тяжелого? Собери 1 lib-ину, и все. Весят они совсем чуть-чуть, а пользы приносят достаточно. Или ты имел ввиду "тяжелый для понимания"? smile Но это надо исправлять, я считаю.


--------------------
- why you call it beta?
- cuz it's betta then nothin'
PM MAIL   Вверх
baldina
Дата 11.7.2011, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



я имел в виду, что не всегда удобно, целесообразно или просто возможно тянуть за собой либы. или даже использовать кучу просто хидеров.
буст рулит, но не надо фанатизма
PM MAIL   Вверх
spyswamp
Дата 11.7.2011, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 1
Всего: 7



baldina, понятное дело. Но по мне, так лучше использовать проверенные решения, чем ковыряться в отладчике. Это я к тому, что сейчас поддерживаю кучу адового кода с самописными итераторами, смарт_птрами, листами и т.п. от таких нефанатов. Знать КАК это работает нужно, я не спорю, но вот использовать в чем-то, кроме школьных или институтских лабораторных, все же, не стоит. Embedded systems не рассматриваем сейчас, там свои замуты. smile


--------------------
- why you call it beta?
- cuz it's betta then nothin'
PM MAIL   Вверх
Earnest
Дата 11.7.2011, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(spyswamp @  11.7.2011,  12:08 Найти цитируемый пост)
лучше использовать проверенные решения

В любом проверенном решении могут быть ошибки - программирование однако. И чем сложнее решение, тем вероятнее ошибки и сложнее их обнаружить и просто понять причину проблемы. Я в бусте ошибки находила.
Данная же задача довольно тривиальна для проприентарного случая (я имею в виду контейнер + разные индексы). А вот гибкое (бустовское) решение может быть достаточно сложным. Не буду утверждать, что это именно так, ибо не  знакома с этим контейнером. Но запрограммировать упомянутый проприентарный контейнер - полчаса, ну час от силы. И ради чего огород городить-то?
Т.е.
Цитата(baldina @  11.7.2011,  12:04 Найти цитируемый пост)
буст рулит, но не надо фанатизма 

Подписываюсь.



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


Опытный
**


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

Репутация: 1
Всего: 7



Earnest, простите, конечно, но "огород" - это именно ваше решение. smile Полчаса-час программирования и годы мучений вместо 3-х минут работы (2 из которых уходят на перекур и кофе).


--------------------
- why you call it beta?
- cuz it's betta then nothin'
PM MAIL   Вверх
Earnest
Дата 11.7.2011, 17:06 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(spyswamp @  11.7.2011,  13:52 Найти цитируемый пост)
и годы мучений

Это только если руки растут сами знаете откуда, чего там программировать-то smile 
Цитата(spyswamp @  11.7.2011,  13:52 Найти цитируемый пост)
вместо 3-х минут работы

Это если имеешь опыт работы с данным классом или концепцией.
А если нет (нельзя же все знать!), то чтобы разобраться и привыкнуть, нужно некоторое время, и это совсем не полчаса.
А автор топика, похоже, не знает, иначе не спрашивал бы.




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


Опытный
**


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

Репутация: 1
Всего: 7



Ладно-ладно, вы меня затроллили. smile WIN-WIN!


--------------------
- why you call it beta?
- cuz it's betta then nothin'
PM MAIL   Вверх
asmdzen
Дата 13.7.2011, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



**


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

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



всем спасибо, после "effective c++" стало понятно что не так с наследованием от list'а, немного пересмотрел задачу и оказалось что совет Earnest самый подходящий (не буду мудрить).
boost тоже не плох, только с ним еще надо разобраться.
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0701 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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