Тщательная ли сортировка JavaScript? - PullRequest
1 голос
/ 05 августа 2020

У меня также есть функция сортировки примерно так:

const mySortingFunction = (a, b) => {
  if (a_before_b(a, b)) return 1;
  if (b_before_a(a, b)) return -1;
  return 0;
}

Давайте оставим a_before_b и b_before_a как черные ящики, так как я думаю, что они только отвлекут от проблемы.

my_unsorted_list.sort(mySortingFunction);

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

Я считаю, что есть 3 возможности.

  • Мои функции черного ящика несовместимы сами с собой или друг с другом
  • Встроенная сортировка JavaScript не является тщательной
  • Оба вышеперечисленных

Чтобы проверить вторую теорию, я вставил console.log({ a, b }) внутрь mySortingFunction. Я думал, что хотя бы один раз для каждой возможной уникальной пары элементов массива.

Но это было гораздо меньше. Примерно в 4 раза больше элементов, чем в списке.

Я думаю, что, поскольку мои функции черного ящика не обрабатывают все возможные случаи и иногда mySortingFunction возвращает 0, вот что вызывает несовершенную сортировку, когда некоторые элементы находятся в положении, которое противоречит тому, что продиктовано функциями черного ящика.

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

Надеюсь, кто-нибудь сможет сказать мне, какая из перечисленных мной возможностей может быть проблемой, или есть что-то еще, что я не рассматриваю.

Для ясности, я не пытаюсь судить JavaScript встроенная сортировка. Когда я спрашиваю, «тщательно ли», я имею в виду, предназначен ли он для использования именно так, как я его использую.

Вот пример того, что я пытаюсь сделать. Как видите, даже если logi c согласован, сортировка не выполняется. Я предполагаю, что в приведенном ниже примере (хотя я еще не уверен) недостаточно условий. Но в моем примере из реальной жизни также возможно, что условия несовместимы.

Я пытаюсь выяснить, какой из них имеет место.

const sorted = ['a', 'b', 'c', 'd'];
const unsorted = ['c', 'd', 'a', 'b'];

const a_before_b = (a, b) => {
  if (a == 'a' && b == 'd') return true;
  if (a == 'b' && b == 'c') return true;
}

const b_before_a = (a, b) => {
  if (b == 'a' && a == 'c') return true;
  if (b == 'b' && a == 'c') return true;
}

const mySortingFunction = (a, b) => {
  if (a_before_b(a, b)) return -1;
  if (b_before_a(a, b)) return 1;
  return 0;
}

console.log(unsorted.sort(mySortingFunction)); // [ 'c', 'a', 'd', 'b' ]

Обновить! Я заметил, что он отсортировал 'c' перед 'b', хотя моя функция сортировки явно указывает, что этого не должно быть:

const b_before_a = (a, b) => {
  if (b == 'a' && a == 'c') return true; 
  if (b == 'b' && a == 'c') return true; // how did c get sorted before b?
}

1 Ответ

0 голосов
/ 05 августа 2020

Алгоритм сортировки работает. Если указана неверная функция сортировки, результат определяется реализацией и является ошибкой в ​​вызывающем коде.

Per 22.1.3.27 Array.prototype.sort :

Если comparefn [..] не является последовательной функцией сравнения для элементов этого массива (см. Ниже), порядок сортировки определяется реализацией. Порядок сортировки также определяется реализацией если comparefn не определен и SortCompare не действует как функция последовательного сравнения.

Это основное c требование для всех видов сравнения. lg n) время, такое как сортировка слиянием или производная, не проверяет все возможные перестановки пар. Если бы сортировка применила сравнение ко всем комбинациям пар, это заняло бы по крайней мере O (n ^ 2) времени - и все равно не было бы гарантировано без согласованной функции сравнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...