Сортировка(значение, ID)
От: Glas  
Дата: 13.03.11 18:53
Оценка:
Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID. Но по времени не укладываюсь в рамки
Re: Сортировка(значение, ID)
От: VEAPUK  
Дата: 13.03.11 19:29
Оценка:
Здравствуйте, Glas, Вы писали:

G>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID. Но по времени не укладываюсь в рамки


ID уникальны? Составной ключ?
Re: Сортировка(значение, ID)
От: MBo  
Дата: 13.03.11 19:40
Оценка:
Здравствуйте, Glas, Вы писали:

G>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID.


В функции сравнения сначала сравниваются значения, а при их равенстве — id. Тогда одной сортировки хватит
Re[2]: Сортировка(значение, ID)
От: Glas  
Дата: 13.03.11 20:28
Оценка:
Здравствуйте, VEAPUK, Вы писали:

VEA>ID уникальны? Составной ключ?


Да, для каждого значения ID уникален, по сути это позиция.
Re[2]: Сортировка(значение, ID)
От: Glas  
Дата: 13.03.11 20:31
Оценка:
Здравствуйте, MBo, Вы писали:

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


G>>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID.


MBo>В функции сравнения сначала сравниваются значения, а при их равенстве — id. Тогда одной сортировки хватит


Если подскажете как это реализовать для алгоритма quicksort, буду премного благодарен.
Re[3]: Сортировка(значение, ID)
От: VEAPUK  
Дата: 13.03.11 20:56
Оценка:
Здравствуйте, Glas, Вы писали:

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


VEA>>ID уникальны? Составной ключ?


G>Да, для каждого значения ID уникален, по сути это позиция.


В смысле?

Так:


ID    Значение
1    2
2    3
1    2
3    5


или


ID    Значение
1    2
2    3
3    2
4    5
Re: Сортировка(значение, ID)
От: dilmah США  
Дата: 13.03.11 21:09
Оценка:
std::vector< std::pair< Value, Id > > vector;
............
std::sort(vector.begin(), vector.end());
Re[3]: Сортировка(значение, ID)
От: Lloyd Россия  
Дата: 13.03.11 21:12
Оценка:
Здравствуйте, Glas, Вы писали:

MBo>>В функции сравнения сначала сравниваются значения, а при их равенстве — id. Тогда одной сортировки хватит


G>Если подскажете как это реализовать для алгоритма quicksort, буду премного благодарен.


"алгоритм quicksort" функцию сравнения принимает? Вот тогда и передавай в него функцию, работающую по описанной схеме.
Re[4]: Сортировка(значение, ID)
От: Glas  
Дата: 13.03.11 21:14
Оценка:
Так

VEA>
VEA>ID    Значение
VEA>1    2
VEA>2    3
VEA>3    2
VEA>4    5
VEA>
Re[4]: Сортировка(значение, ID)
От: Glas  
Дата: 13.03.11 21:19
Оценка:
Здравствуйте, Lloyd, Вы писали:

вот реализация алгоритма, int * idx массив ID, куда вставить сравнение?

void Matrix::QuickSort(Matrix matrix, int * idx, int first, int last)
{
    double p = *matrix((last - first) / 2 + first);
    double temp;
    int idxTemp;
    int i = first;
    int j = last;
    while (i <= j)
    {
        while (*matrix(i) < p && i <= last) ++i;
        while (*matrix(j) > p && j >= first) --j;
        if (i <= j)
        {
            temp = *matrix(i);
            idxTemp = idx[i - 1];
            *matrix(i) = *matrix(j);
            *matrix(j) = temp;
            idx[i - 1] = idx[j - 1];
            idx[j - 1] = idxTemp;
            ++i; --j;
        }
    }
    if (j > first) QuickSort(matrix, idx, first, j);
    if (i < last) QuickSort(matrix, idx, i, last);
}
Re[2]: Сортировка(значение, ID)
От: Glas  
Дата: 13.03.11 21:21
Оценка:
Здравствуйте, dilmah, Вы писали:

D>std::vector< std::pair< Value, Id > > vector;

D>............
D>std::sort(vector.begin(), vector.end());

динамические массивы меня вообще разочаровали. Там только на вставке значение по времени потери чего стоят.
Re[5]: Сортировка(значение, ID)
От: Muxa  
Дата: 13.03.11 21:33
Оценка: +1
G>вот реализация алгоритма, int * idx массив ID, куда вставить сравнение?

void Matrix::QuickSort(Matrix matrix, int * idx, int first, int last)
{
//...
        while (*matrix(i) < p && i <= last) ++i;
        while (*matrix(j) > p && j >= first) --j;
//...
}
Re: Сортировка(значение, ID)
От: Glas  
Дата: 13.03.11 21:34
Оценка:
Здравствуйте, Glas, Вы писали:

G>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID. Но по времени не укладываюсь в рамки


Мда, а причина то оказывается не в том, что сортировка в 2 прохода Тупо все циклы занимают 50% времени, 45% на перемещение данных и 5% на досортировку ID.
Re[3]: Сортировка(значение, ID)
От: Буравчик Россия  
Дата: 13.03.11 22:03
Оценка:
Здравствуйте, Glas, Вы писали:

G>Да, для каждого значения ID уникален, по сути это позиция.


1. Если ID — это позиция, значит нельзя менять порядок равных элементов. Т.е. равные элементы остаются в том порядке, в котором они были в исходном массиве. Называется это дело "stable sort" (устойчивая или стабильная сортировка).

2. STL содержит функцию stable_sort(), которая решает данную задачу. http://www.cplusplus.com/reference/algorithm/stable_sort/

3. Некоторые алгоритмы сортировки изначально являются стабильными. Обычный quicksort к таким не относится. Можно выбрать другой: http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms — смотреть столбец "stable"

4. Алгоритм quicksort можно сделать стабильным. Нужно выбирать такой опорный элемент, чтобы правее него не было других равных ему элементов.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Best regards, Буравчик
Re[3]: Сортировка(значение, ID)
От: Stanislav V. Zudin Россия  
Дата: 13.03.11 22:04
Оценка:
Здравствуйте, Glas, Вы писали:

G>динамические массивы меня вообще разочаровали. Там только на вставке значение по времени потери чего стоят.


Дык, если знаешь количество элементов заранее, то reserve(). Не?
Ну и #define _SECURE_SCL 0, если пользуешься stl'ем из VisualStudio.
_____________________
С уважением,
Stanislav V. Zudin
Re[4]: Сортировка(значение, ID)
От: Glas  
Дата: 13.03.11 22:37
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>1. Если ID — это позиция, значит нельзя менять порядок равных элементов. Т.е. равные элементы остаются в том порядке, в котором они были в исходном массиве. Называется это дело "stable sort" (устойчивая или стабильная сортировка).


Б>2. STL содержит функцию stable_sort(), которая решает данную задачу. http://www.cplusplus.com/reference/algorithm/stable_sort/


Б>3. Некоторые алгоритмы сортировки изначально являются стабильными. Обычный quicksort к таким не относится. Можно выбрать другой: http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms — смотреть столбец "stable"


Б>4. Алгоритм quicksort можно сделать стабильным. Нужно выбирать такой опорный элемент, чтобы правее него не было других равных ему элементов.


1. да я в терминологии ноль
2. не подходит, так как массив внутри класса.
3. Спасибо за табличку, сейчас себе попробую, что-нибудь подобрать, хотя heapsort почему-то оказался хуже
4. В массиве множество повторяющихся элементов, не подобрать такой элемент.
Re[5]: Сортировка(значение, ID)
От: minorlogic Украина  
Дата: 14.03.11 05:18
Оценка:
Реализация кстати довольно слабая, может возьмете готовую ? может даже intro_sort ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: Сортировка(значение, ID)
От: minorlogic Украина  
Дата: 14.03.11 05:20
Оценка:
Здравствуйте, Glas, Вы писали:

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


G>>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID. Но по времени не укладываюсь в рамки


G>Мда, а причина то оказывается не в том, что сортировка в 2 прохода Тупо все циклы занимают 50% времени, 45% на перемещение данных и 5% на досортировку ID.


Тогда сортиру только внешний массив с индексами перестановок.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[6]: Сортировка(значение, ID)
От: Glas  
Дата: 14.03.11 06:53
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Реализация кстати довольно слабая, может возьмете готовую ? может даже intro_sort ?

Я сейчас все сортировки перебирать буду. Вообще из matlaba бы реализацию вытащить. Там этот массив быстрее на порядок сортируется.
Re[5]: Сортировка(значение, ID)
От: minorlogic Украина  
Дата: 14.03.11 07:38
Оценка: +1
Здравствуйте, Glas, Вы писали:

G>Здравствуйте, Буравчик, Вы писали:


Б>>2. STL содержит функцию stable_sort(), которая решает данную задачу. http://www.cplusplus.com/reference/algorithm/stable_sort/


G>2. не подходит, так как массив внутри класса.



Не вижу логической связи. Подробнее ?
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: Сортировка(значение, ID)
От: Veminz Украина  
Дата: 14.03.11 08:28
Оценка:
Здравствуйте, Glas, Вы писали:

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


G>>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID. Но по времени не укладываюсь в рамки


G>Мда, а причина то оказывается не в том, что сортировка в 2 прохода Тупо все циклы занимают 50% времени, 45% на перемещение данных и 5% на досортировку ID.


Из примера кода приведенного ранее:


    while (i <= j)
    {
        while (*matrix(i) < p && i <= last) ++i;
        while (*matrix(j) > p && j >= first) --j;
        if (i <= j)
        {
            temp = *matrix(i);
            idxTemp = idx[i - 1];
            *matrix(i) = *matrix(j);
            *matrix(j) = temp;
            idx[i - 1] = idx[j - 1];
            idx[j - 1] = idxTemp;
            ++i; --j;
        }
    }



Возможно внутри вызовов типа matrix(i) спрятаны еще циклы?
... Если в первый момент идея не кажется абсурдной, она безнадёжна. © Альберт Эйнштейн
Re[5]: Сортировка(значение, ID)
От: Буравчик Россия  
Дата: 14.03.11 10:43
Оценка:
Здравствуйте, Glas, Вы писали:

G>1. да я в терминологии ноль


Речь не о терминологии, а о свойстве алгоритмов сортировки. Если ID не является частью сортируемых элементов, а искусственно введен для того чтобы не перемешивать равные элементы, то более эффективным будет использовать уже готовые алгоритмы стабильной сортировки, для которых это условие соблюдается автоматически.

G>2. не подходит, так как массив внутри класса.


Не понял почему не подходит.

G>3. Спасибо за табличку, сейчас себе попробую, что-нибудь подобрать, хотя heapsort почему-то оказался хуже


Heapsort не является устойчивым.

В принципе, можно взять любой алгоритм сортировки (не обязательно устойчивый) и сортировать пары (значение_элемента, ID_элемента). Но тогда чем quicksort не устроил?

G>4. В массиве множество повторяющихся элементов, не подобрать такой элемент.


Это можно сделать всегда. Нужно выбрать любой опорный элемент, а затем взять "самый правый" из равных ему. В любом случае алгоритм с учетом этих преобразований работает медленнее, чем обычный quicksort.
Best regards, Буравчик
Re[6]: Сортировка(значение, ID)
От: Glas  
Дата: 14.03.11 11:19
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Не понял почему не подходит.


Потому что перекинуть 3млн значений из одного массива в другой займет приличное время.

Б>Heapsort не является устойчивым.


Да фиг с ним с устойчивостью, он в принципе оказался медленнее намного, хотя не должен был проиграть.

Б>В принципе, можно взять любой алгоритм сортировки (не обязательно устойчивый) и сортировать пары (значение_элемента, ID_элемента). Но тогда чем quicksort не устроил?


По времени не укладывается Сейчас буду рыть в сторону реализации сортировки в матлабе, там этот же массив сортируется за 1-2 секунды
Re[3]: Сортировка(значение, ID)
От: Glas  
Дата: 14.03.11 11:23
Оценка:
Здравствуйте, Veminz, Вы писали:

V>
V>    while (i <= j)
V>    {
V>        while (*matrix(i) < p && i <= last) ++i;
V>        while (*matrix(j) > p && j >= first) --j;
V>        if (i <= j)
V>        {
V>            temp = *matrix(i);
V>            idxTemp = idx[i - 1];
V>            *matrix(i) = *matrix(j);
V>            *matrix(j) = temp;
V>            idx[i - 1] = idx[j - 1];
V>            idx[j - 1] = idxTemp;
V>            ++i; --j;
V>        }
V>    }
V>



V>Возможно внутри вызовов типа matrix(i) спрятаны еще циклы?


Matrix(i) это перегруженный оператор для обращения к данным, циклов там нет
Re[7]: Сортировка(значение, ID)
От: Буравчик Россия  
Дата: 14.03.11 11:51
Оценка:
Здравствуйте, Glas, Вы писали:

G>Потому что перекинуть 3млн значений из одного массива в другой займет приличное время.


Зачем перекидывать? Почему нельзя использовать сравнивающую функцию (comparator)?

G>По времени не укладывается Сейчас буду рыть в сторону реализации сортировки в матлабе, там этот же массив сортируется за 1-2 секунды


Quicksort может быть медленным, если выбираются неудачные опорные точки. Сколько у тебя времени выполняется quicksort?

Стало интересно, можешь код выложить и исходные данные?
Best regards, Буравчик
Re[8]: Сортировка(значение, ID)
От: Glas  
Дата: 14.03.11 12:13
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Зачем перекидывать? Почему нельзя использовать сравнивающую функцию (comparator)?


Данные хранятся в классе матрицы, при сортировке надо помимо отсортированных значений вернуть еще их начальные позиции(ID), которые также должны быть упорядочены(ну то есть стабильная сортировка). Может я не совсем Вас правильно понимаю.

Б>Quicksort может быть медленным, если выбираются неудачные опорные точки. Сколько у тебя времени выполняется quicksort?


Б>Стало интересно, можешь код выложить и исходные данные?


Скорее всего дело как раз в опорной точке, потому что пересортировка по ID проходит быстро для того же массива.
Сейчас у меня 5 секунд. Надо до 1 сократить

void Matrix::Sort(Matrix matrix, Matrix * sortedMatrix, int* idx)
{
    sortedMatrix->Copy(&matrix);//входную матрицу менять нельзя

    if (sortedMatrix->RowsNumber() != 1 && sortedMatrix->ColumnsNumber() != 1)//если не вектор
    {
        sortedMatrix = &sortedMatrix->ToVector();
    }

    for (int i = 1; i <= sortedMatrix->RowsNumber(); i++)
    {
        idx[i - 1] = i;
    }

    int rows = sortedMatrix->RowsNumber();//длина вектора

    QuickSort(*sortedMatrix, idx, 1, rows);
    QuickSortIndexes(*sortedMatrix, idx);//тут время выполнения 0.5с
}
void Matrix::QuickSort(Matrix matrix, int * idx, int first, int last)
{
    double p = *matrix((last - first) / 2 + first);
    double temp;
    int idxTemp;
    int i = first;
    int j = last;
    while (i <= j)
    {
        while (*matrix(i) < p && i <= last) ++i;
        while (*matrix(j) > p && j >= first) --j;
        if (i <= j)
        {
            temp = *matrix(i);
            idxTemp = idx[i - 1];
            *matrix(i) = *matrix(j);
            *matrix(j) = temp;
            idx[i - 1] = idx[j - 1];
            idx[j - 1] = idxTemp;
            ++i; --j;
        }
    }
    if (j > first) QuickSort(matrix, idx, first, j);
    if (i < last) QuickSort(matrix, idx, i, last);
}

void Matrix::QuickSortIndexes(Matrix matrix, int * idx)
{
    int first;
    int last;
    for (int i = 1; i <= matrix.RowsNumber(); i++)
    {
        first = i - 1;
        if (i != matrix.RowsNumber())
        {
            while (*matrix(i) == *matrix(i + 1))
            {
                i++;
                if (i == matrix.RowsNumber())
                    break;
            }
            last = i - 1;
            QuickSort(idx, first, last);
        }
    }
}
Re[8]: Сортировка(значение, ID)
От: Glas  
Дата: 14.03.11 12:31
Оценка:
Сейчас попробовал stable_sort, это вообще ужас. цикл по заполнению вектора только секунды 3 занимает.
        vector<pair<double, int>> values;
    vector<pair<double, int>>::iterator it;
    values.resize(sortedMatrix->RowsNumber());
    
    int i = 1;
    for (it = values.begin(); it != values.end(); it++, i++)
        {
        (*it).first = *(*sortedMatrix)(i);
        (*it).second = i - 1;
        }
    stable_sort(values.begin(), values.end());
Re[9]: Сортировка(значение, ID)
От: Stanislav V. Zudin Россия  
Дата: 14.03.11 12:55
Оценка:
Здравствуйте, Glas, Вы писали:

G>Сейчас попробовал stable_sort, это вообще ужас. цикл по заполнению вектора только секунды 3 занимает.

G>
G>        vector<pair<double, int>> values;
G>    vector<pair<double, int>>::iterator it;
G>    values.resize(sortedMatrix->RowsNumber());
    
G>    int i = 1;
G>    for (it = values.begin(); it != values.end(); it++, i++)
G>        {
G>        (*it).first = *(*sortedMatrix)(i);
G>        (*it).second = i - 1;
G>        }
G>    stable_sort(values.begin(), values.end());
G>


Попробуй, для начала, инициализацию по умолчанию + присваивание заменить на одну инициализацию.
Раза в 4 можно ускорить:

vector<pair<double, int>> values;
values.reserve(sortedMatrix->RowsNumber());

for(int i = 1, iE = sortedMatrix->RowsNumber(); i <= iE; ++i)
{
   values.push_back( std::make_pair( *(*sortedMatrix)(i), i-1) );
}
_____________________
С уважением,
Stanislav V. Zudin
Re[10]: Сортировка(значение, ID)
От: Stanislav V. Zudin Россия  
Дата: 14.03.11 12:58
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Попробуй, для начала, инициализацию по умолчанию + присваивание заменить на одну инициализацию.

Пожалуй погорячился — в релизе по скорости сравнится.
_____________________
С уважением,
Stanislav V. Zudin
Re[9]: Сортировка(значение, ID)
От: Буравчик Россия  
Дата: 14.03.11 12:59
Оценка:
Здравствуйте, Glas, Вы писали:

G>Данные хранятся в классе матрицы, при сортировке надо помимо отсортированных значений вернуть еще их начальные позиции(ID), которые также должны быть упорядочены(ну то есть стабильная сортировка). Может я не совсем Вас правильно понимаю.


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

Т.е. заводим массив индексов от 0 до N-1 и будем сортировать его в зависимости от того, на какие элементы матрицы эти индексы ссылаются. Для этого можно ввести компаратор (x,y — индексы):
cmp(x,y) = if (matrix(x) == matrix(y)) then x<y else matrix(x) < matrix(y)

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


G>Скорее всего дело как раз в опорной точке, потому что пересортировка по ID проходит быстро для того же массива.

G>Сейчас у меня 5 секунд. Надо до 1 сократить

Попробуй выбрать другую опорную точку — не с середины, а с начала или с конца?
Может дело в сложности matrix(i)?
На всякий случай спрошу, оптимизации включены?
Best regards, Буравчик
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.