Это просто небольшие изменения в вашей функции сравнения, чтобы сделать библиотеку qsort стабильной.См. Ссылку здесь
Что-то вроде ниже должно помочь (не проверено, будьте осторожны):
int comp_on_price(const void *a, const void *b)
{
if ((*(B *)a).price < (*(B *)b).price)
return 1;
else if ((*(B *)a).price > (*(B *)b).price)
return -1;
else
// if zero order by addresses
return a-b;
}
Это будет работать, если вы можете гарантировать, что a и b находятся вто же адресное пространство (два указателя в одном массиве) и то, что каждое сравнение дает больший общий порядок массива, адреса более низких структур будут иметь тенденцию становиться еще медленнее.Это верно для пузырьковых сортов или аналогичных.Это также будет работать для тривиальной реализации QucikSort (которой не является qsort).Однако для других алгоритмов или любого алгоритма, использующего дополнительное адресное пространство для временного хранения (возможно, в целях оптимизации), это свойство не будет истинным.
Если то, что вы сортируете, содержит какой-либо уникальный идентификатор в сравниваемых элементах (в текущем примере это, вероятно, верно для идентификатора поля), другой способ сделать сортировку стабильной - сравнить эти элементы.Вы также можете добавить такой уникальный ключ в новое поле для этой цели, но, поскольку он использует больше памяти, вы должны рассмотреть третий вариант, описанный ниже, прежде чем делать это.
Мой предпочтительный метод все равно будет третьим,не сортируйте массив структур напрямую, а сортируйте указатели на элементы структуры.Это имеет несколько хороших свойств.Сначала вы можете сравнить массивы указанной структуры, так как она не изменится и сделает сортировку стабильной.
Функция сравнения станет примерно такой:
int comp_on_price(const void *a, const void *b)
{
if ((*(B **)a)->price < (*(B **)b)->price)
return 1;
else if ((*(B **)a)->price > (*(B **)b)->price)
return -1;
else
// if zero, order by addresses
return *(B **)a-*(B **)b;
}
Другое хорошоСвойства заключаются в том, что он избегает перемещения структур во время сортировки, ему нужно только перемещать указатели, и это может сэкономить время.Вы также можете сохранить несколько таких массивов указателей, что позволяет одновременно выполнять несколько упорядоченных обращений к элементам массива.
Недостатками является то, что требуется немного памяти и что доступ к элементам немного медленнее (на один уровень косвенности больше).