Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID. Но по времени не укладываюсь в рамки
Здравствуйте, Glas, Вы писали:
G>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID. Но по времени не укладываюсь в рамки
Здравствуйте, Glas, Вы писали:
G>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID.
В функции сравнения сначала сравниваются значения, а при их равенстве — id. Тогда одной сортировки хватит
Здравствуйте, MBo, Вы писали:
MBo>Здравствуйте, Glas, Вы писали:
G>>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID.
MBo>В функции сравнения сначала сравниваются значения, а при их равенстве — id. Тогда одной сортировки хватит
Если подскажете как это реализовать для алгоритма quicksort, буду премного благодарен.
Здравствуйте, Glas, Вы писали:
G>Здравствуйте, VEAPUK, Вы писали:
VEA>>ID уникальны? Составной ключ?
G>Да, для каждого значения ID уникален, по сути это позиция.
Здравствуйте, Glas, Вы писали:
MBo>>В функции сравнения сначала сравниваются значения, а при их равенстве — id. Тогда одной сортировки хватит
G>Если подскажете как это реализовать для алгоритма quicksort, буду премного благодарен.
"алгоритм quicksort" функцию сравнения принимает? Вот тогда и передавай в него функцию, работающую по описанной схеме.
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;
//...
}
Здравствуйте, Glas, Вы писали:
G>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID. Но по времени не укладываюсь в рамки
Мда, а причина то оказывается не в том, что сортировка в 2 прохода Тупо все циклы занимают 50% времени, 45% на перемещение данных и 5% на досортировку ID.
Здравствуйте, Glas, Вы писали:
G>Да, для каждого значения ID уникален, по сути это позиция.
1. Если ID — это позиция, значит нельзя менять порядок равных элементов. Т.е. равные элементы остаются в том порядке, в котором они были в исходном массиве. Называется это дело "stable sort" (устойчивая или стабильная сортировка).
Здравствуйте, Буравчик, Вы писали:
Б>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. В массиве множество повторяющихся элементов, не подобрать такой элемент.
Здравствуйте, Glas, Вы писали:
G>Здравствуйте, Glas, Вы писали:
G>>Есть массив значений, каждое значение имеет свой ID. Нужно отсортировать этот массив так, чтобы одинаковые значения были отсортированы по ID. Сейчас я сортирую 2 раза, сперва массив, потом ID. Но по времени не укладываюсь в рамки
G>Мда, а причина то оказывается не в том, что сортировка в 2 прохода Тупо все циклы занимают 50% времени, 45% на перемещение данных и 5% на досортировку ID.
Тогда сортиру только внешний массив с индексами перестановок.
Здравствуйте, minorlogic, Вы писали:
M>Реализация кстати довольно слабая, может возьмете готовую ? может даже intro_sort ?
Я сейчас все сортировки перебирать буду. Вообще из matlaba бы реализацию вытащить. Там этот массив быстрее на порядок сортируется.
Здравствуйте, Glas, Вы писали:
G>Здравствуйте, Буравчик, Вы писали:
Б>>2. STL содержит функцию stable_sort(), которая решает данную задачу. http://www.cplusplus.com/reference/algorithm/stable_sort/
G>2. не подходит, так как массив внутри класса.
Здравствуйте, 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) спрятаны еще циклы?
Здравствуйте, Glas, Вы писали:
G>1. да я в терминологии ноль
Речь не о терминологии, а о свойстве алгоритмов сортировки. Если ID не является частью сортируемых элементов, а искусственно введен для того чтобы не перемешивать равные элементы, то более эффективным будет использовать уже готовые алгоритмы стабильной сортировки, для которых это условие соблюдается автоматически.
G>2. не подходит, так как массив внутри класса.
Не понял почему не подходит.
G>3. Спасибо за табличку, сейчас себе попробую, что-нибудь подобрать, хотя heapsort почему-то оказался хуже
Heapsort не является устойчивым.
В принципе, можно взять любой алгоритм сортировки (не обязательно устойчивый) и сортировать пары (значение_элемента, ID_элемента). Но тогда чем quicksort не устроил?
G>4. В массиве множество повторяющихся элементов, не подобрать такой элемент.
Это можно сделать всегда. Нужно выбрать любой опорный элемент, а затем взять "самый правый" из равных ему. В любом случае алгоритм с учетом этих преобразований работает медленнее, чем обычный quicksort.
Здравствуйте, Буравчик, Вы писали:
Б>Не понял почему не подходит.
Потому что перекинуть 3млн значений из одного массива в другой займет приличное время.
Б>Heapsort не является устойчивым.
Да фиг с ним с устойчивостью, он в принципе оказался медленнее намного, хотя не должен был проиграть.
Б>В принципе, можно взять любой алгоритм сортировки (не обязательно устойчивый) и сортировать пары (значение_элемента, ID_элемента). Но тогда чем quicksort не устроил?
По времени не укладывается Сейчас буду рыть в сторону реализации сортировки в матлабе, там этот же массив сортируется за 1-2 секунды
Здравствуйте, Glas, Вы писали:
G>Потому что перекинуть 3млн значений из одного массива в другой займет приличное время.
Зачем перекидывать? Почему нельзя использовать сравнивающую функцию (comparator)?
G>По времени не укладывается Сейчас буду рыть в сторону реализации сортировки в матлабе, там этот же массив сортируется за 1-2 секунды
Quicksort может быть медленным, если выбираются неудачные опорные точки. Сколько у тебя времени выполняется quicksort?
Стало интересно, можешь код выложить и исходные данные?
Здравствуйте, Буравчик, Вы писали:
Б>Зачем перекидывать? Почему нельзя использовать сравнивающую функцию (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);
}
}
}
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Попробуй, для начала, инициализацию по умолчанию + присваивание заменить на одну инициализацию.
Пожалуй погорячился — в релизе по скорости сравнится.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, 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)?
На всякий случай спрошу, оптимизации включены?