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

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

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>


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

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

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

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

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

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



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>


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

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


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

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

        if (i != idx)                                        // Обменять местами
            std::swap(ptr[idx], ptr[i]);
    }
}
_____________________
С уважением,
Stanislav V. Zudin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.