Модераторы: 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   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0588 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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