LINUX.ORG.RU

Сортировка матрицы посредством std::sort. Изобретать ли итератор?

 ,


0

2

Есть матрица в виде массива new T[cCols*cRows] по строчная (строка1, строка2, ...). Как бы ее сортировать посредством std::sort? Есть ли что готовое на эту тему? Или же std::qsort использовать?

======================================================

UPD: В среднем алгоритм получился такой (здесь писалось без проверки, у меня другие классы):

void M::sortByCol(uint iCol) {

    vector<pair<uint,uint>> listIdx;
    // first - откуда взять после сортировки,
    // second - куда поместить (обратный индекс)
    for (uint ii = 0; ii < cRows; ++ii)
        listIdx.push_back({ii,0});

    std::sort(listIdx.begin(), listIdx.end(),
           [&](const auto &p1, const auto &p2) -> bool {
               return getData(iCol, p1.first) < getData(iCol, p2.first); });

    for (uint ii = 0; ii < cRows; ++ii)
        listIdx[listIdx[ii].first].second = ii; // обратный индекс

    for (uint ii = 0; ii < cRows-1; ++ii) {
        auto &p = listIdx[ii];
        uint iSrc = p.first; // откуда берется в тек.строку
        if (iSrc == ii) continue;
        swapRows(ii, iSrc);
        listIdx[p.second].first = iSrc; // а прежние данные после будут
        listIdx[iSrc].second = p.second; //  браться уже отсюда.
    }
}

Как здесь упоминалось, колонку сортировки можно так же предварительно сложить в вектор для сортировки для ускорения, но это уже по желанию и необходимости.



Последнее исправление: victor79 (всего исправлений: 2)

Смотря что вы понимаете под отсортированной матрицей.

Как бы ее сортировать посредством std::sort?

Пишете итераторы, отдаете их в std::sort.

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

Пишете итераторы,

Так я про это и спрашиваю, есть ли готовое? Там существенно заморочный итератор для этого случая.

Сортировать нужно по одной из колонок, но это не суть, т.к. это уже реализация компаратора, что не составляет проблемы.

victor79
() автор топика
Последнее исправление: victor79 (всего исправлений: 1)
Ответ на: комментарий от ox55ff

Это суть. Что подаётся на вход компаратора?

Как вариант, такой вот вариант:

template <class T>
struct M {
   T *ptr = nullptr;
   M(uint cCols, uint cRows, const T *data);
   ...
   void sort(uint iColCmp) {
      std::sort(begin(), end(), [&](const auto &r1, const auto &r2) {
         return getValue(r1, iColCmp) < getValue(r2, iColCmp);
      });
   }
};
Согласно этому примеру это const auto &, которые в свою очередь является разименовыванием итератора, что в свою очередь может быть номер строки, объектом строки, указателем строки. Это будет тем, что удобней будет в реализации этой схемы. На текущий момент у меня есть класс:
struct Row {
   M *mtx = nullptr;
   uint iRow = 0;
   ...
};
но это не обязательно к использованию в сортировке, или может быть конструируемо уже внутри компаратора. Итератора пока нет совсем.

Тут то ли идти путем Си - qsort и без заморочек (почти), то ли реализовывать random-access iterator.

victor79
() автор топика

либо написать свой класс итератора с реализованным методом swap (внутри которого будет очевидно сидеть std::swap_ranges), либо отсортировать поэлементно с компаратором типа «если два элемента в одной строке, то сортируем по индексу, иначе по колонке». Но во 2-м случае очевидно будет большая сложность.

Lrrr ★★★★★
()
Ответ на: комментарий от Lrrr

Смотрю я с тоской на реализации итераторов:

https://stackoverflow.com/questions/8054273/how-to-implement-an-stl-style-ite...

https://stackoverflow.com/questions/7758580/writing-your-own-stl-container/77...

Можно заюзать std::stable_sort. Только что вычитал, сохраняет порядок строк внутри строк с одинаковым значением сортировки. Но она может быть N*log2^2(N)

victor79
() автор топика

Поместить указатели на строки в вектор ( например vector<std::pair<char*,char*>>{{begin, end}, …} ), отсортировать вектор, заменить диапазоны через какой-нибудь std::swap_range?

pavlick ★★
()
Ответ на: комментарий от pavlick

Поместить указатели на строки в вектор ( например vector<std::pair<char*,char*>>{{begin, end}, …} ), отсортировать вектор, заменить диапазоны через какой-нибудь std::swap_range?

Спасибо, похоже так и придется делать.

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

   typename iterator_traits<_RandomAccessIterator>::value_type
   __val = _GLIBCXX_MOVE(*__i);
   _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1);
   *__first = _GLIBCXX_MOVE(__val);

---

UPD: Да, этот вариант оказался предельно простым, и сделался за пару минут. Вместо заморочного итераторного.

victor79
() автор топика
Последнее исправление: victor79 (всего исправлений: 1)
Ответ на: комментарий от victor79

Сортировать нужно по одной из колонок, но это не суть, т.к. это уже реализация компаратора, что не составляет проблемы.

Постановка задачи не очень понятная. Если Вы имеете ввиду, что при сортировке переставляются строки матрицы - то очевидно определить новый порядок строк при помощи std::sort а потом переставить строки. Для этого проще скопировать колонку в вектор пар (значение, номер строки), отсортировать этот вектор а потом уже заниматься перестановками.

Но если такая операция является частой, то выбранное Вами представление матрицы выглядит не айс.

AntonI ★★★★
()
Ответ на: комментарий от AntonI

Для этого проще скопировать колонку в вектор пар (значение, номер строки)

Не, там даже пары номер-значение не нужно. Достаточно вектора индексов строк, а компаратор уже из исходной матрицы достает значение по индексу для сравнения. Или просто вектор указателей.

victor79
() автор топика
Последнее исправление: victor79 (всего исправлений: 1)
Ответ на: комментарий от victor79

Достать то достает, но работать будет дольше. При каждом обращении к элементу лишняя разадресация пойнтера.

AntonI ★★★★
()
Ответ на: комментарий от in_dance

Тут в начале бы определиться что такое отсортированная матрица

Я свой вопрос решил. Если Вы считаете, что мой вопрос назывался как-то по другому, можете продемонстрировать Вашу эрудированность. Я то же тогда буду знать.

victor79
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.