Re[6]: std::map Вопрос по сортировки элементов
От: Anton_Savickiy  
Дата: 12.03.14 10:13
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

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


SVZ>Не удержусь, еще немного покритикую.


A_S>>a) STL

A_S>>
A_S>>struct DATA
A_S>>{
A_S>>    int    cmd;
A_S>>    float    var;
A_S>>};

A_S>>struct DATA_C
A_S>>{
A_S>>    FILETIME    ft;
A_S>>    DATA        dt[1000];
A_S>>};

A_S>>struct sort_rule
A_S>>{
A_S>>    bool operator() (DATA_C i, DATA_C j)
A_S>>    {return (CompareFileTime(&i.ft,&j.ft)==-1) ? true:false;}
A_S>>} sort_object;

A_S>>DATA_C d[NUM];
A_S>>SYSTEMTIME st;
A_S>>GetLocalTime(&st);

A_S>>for(int i=0;i<NUM;i++)
A_S>>{    
A_S>>    st.wMilliseconds = (WORD)rand()%1000;
A_S>>    SystemTimeToFileTime(&st,&d[i].ft);
A_S>>}

A_S>>vector<DATA_C> vecObj(d,d+NUM);
A_S>>sort(vecObj.begin(), vecObj.end(),sort_object);  // #1
A_S>>


SVZ>#1 — Функтор имеет смысл использовать тогда, когда требуется хранить состояние или какие-то данные для сортировки. Например, упорядочить надо по данным, которых нет внутри DATA_C. Тогда внутри функтора можно хранить указатель на внешние данные. В данном случае можно обойтись функцией сравнения (тупо меньше кода ).


SVZ>Еще один прием: если элементы коллекции очень "тяжелые" и их копирование может быть накладным, либо требуется сортировка по разным критериям, то стоит сортировать индексы элементов. Заводится отдельный массив, в который складываются индексы от 0 до NUM:


SVZ>
SVZ>std::vector<int> indexes(NUM);
SVZ>for(int i = 0;  i < NUM; ++i)   // Можно использовать std::generate
SVZ>   indexes[i] = i;

SVZ>class Comparator
SVZ>{
SVZ>   public:
SVZ>     Comparator(const vector<DATA_C>* vecObj) : m_vecObj(vecObj) {}
SVZ>     bool operator()(int lv, int rv) const
SVZ>     {
SVZ>         return CompareFileTime(&(*m_vecObj)[lv].ft, &(*m_vecObj)[rv].ft);
SVZ>     }
SVZ>   private:
SVZ>     const vector<DATA_C>* m_vecObj; // <-- В принципе можно использовать ссылку, а не указатель
SVZ>};

SVZ>std::sort(indexes.begin(), indexes.end(), Comparator(&vecObj)); // <-- Можно обойтись временным объектом компаратора

SVZ>// Обход по упорядоченным элементам:
SVZ>for(std::vector<int>::const_iterator it = indexes.begin(), itE = indexes.end(); it != itE; ++it)
SVZ>{
SVZ>   DoSomething( vecObj[*it]); 
SVZ>}
SVZ>



A_S>>
A_S>>void selectSortS(DATA_C* ptr,int size)
A_S>>{
A_S>>    DATA_C tmp;
A_S>>    int idx;
A_S>>    for(int i=0;i<size;++i)
A_S>>    { 
A_S>>        idx = i; 
A_S>>    memcpy(&tmp,&ptr[i],sizeof(DATA_C));
A_S>>        for(int j=i+1;j<size;++j)
A_S>>        {
A_S>>        if(CompareFileTime(&ptr[j].ft,&tmp.ft)==-1)
A_S>>            {
A_S>>               idx = j; 
A_S>>               memcpy(&tmp,&ptr[j],sizeof(DATA_C));
A_S>>            }
A_S>>        }

A_S>>        memcpy(&ptr[idx],&ptr[i],sizeof(DATA_C));
A_S>>        memcpy(&ptr[i],&tmp,sizeof(DATA_C));
A_S>>    }
A_S>>}

A_S>>


SVZ>Т.к. это С++, а не С, то нет необходимости возиться с memcpy (за исключением определенных экзотических случаев).

SVZ>Копировать структуры можно как обычные переменные:

SVZ>
A_S>>        memcpy(&ptr[idx],&ptr[i],sizeof(DATA_C));
A_S>>        memcpy(&ptr[i],&tmp,sizeof(DATA_C));
SVZ>    ptr[idx] = ptr[i];
SVZ>    ptr[i] = tmp;
SVZ>


SVZ>А если делать совсем правильно, то нет смысла многократно перезаписывать tmp, достаточно сохранять индекс.


SVZ>
SVZ>void selectSortS(DATA_C* ptr,int size)
SVZ>{
SVZ>    int idx;
SVZ>    for(int i=0;i<size;++i)
SVZ>    { 
SVZ>        idx = i; 
SVZ>        for(int j=i+1;j<size;++j)                            // Для каждого последующего элемента
SVZ>        {
SVZ>        if(CompareFileTime(&ptr[j].ft,&ptr[idx].ft) < 0) // Если найден элемент меньше текущего
SVZ>            {
SVZ>               idx = j;                                      // Запомнить индекс
SVZ>            }
SVZ>        }

SVZ>        if (i != idx)                                        // Обменять местами
SVZ>            std::swap(ptr[idx], ptr[i]);
SVZ>    }
SVZ>}

SVZ>


Спасибо Станислав за критику и рекомендации.
Забавный пример с очень "тяжелыми" данными, но его нужно обмозговать, с ходу как то не очень.
Ваша оптимизация selectSortS дала еще 200мс выигрыша.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.