Есть ли способ измерить, насколько отсортирован список?
Я имею в виду, что речь идет не о знании, отсортирован ли список (булево), а о чем-то вроде коэффициента «сортировки», что-то вроде коэффициента корреляции в статистике.
Например,
Если элементы списка расположены в порядке возрастания, тогда их скорость будет 1,0
Если список отсортирован по убыванию, его скорость будет -1,0
Если список почти отсортирован по возрастанию, его скорость будет 0,9 или какое-либо значение, близкое к 1.
Если список не отсортирован вообще (случайно), его скорость будет близка к 0
Я пишу небольшую библиотеку в Scala для практики. Я думаю, что скорость сортировки была бы полезна, но я не нахожу никакой информации о чем-то подобном. Может быть, я не знаю адекватных терминов для концепции.
Ответы:
Вы можете просто посчитать количество инверсий в списке.
инверсия
Инверсия в последовательности элементов типа
T
представляет собой пару элементов последовательности, которые появляются не по порядку в соответствии с некоторым порядком<
на множествеT
's.Из Википедии :
Чтобы сделать эти определения более понятными, рассмотрим пример последовательности
9, 5, 7, 6
. Эта последовательность имеет инверсии(0,1), (0,2), (0,3), (2,3)
и номер инверсии4
.Если вы хотите значение между
0
и1
, вы можете разделить число инверсии наN choose 2
.Чтобы на самом деле создать алгоритм для вычисления этой оценки того, насколько отсортирован список, у вас есть два подхода:
Подход 1 (детерминированный)
Измените свой любимый алгоритм сортировки, чтобы отслеживать, сколько инверсий он исправляет во время работы. Хотя это нетривиально и имеет различные реализации в зависимости от выбранного вами алгоритма сортировки, вы получите алгоритм, который не дороже (с точки зрения сложности), чем алгоритм сортировки, который вы начали.
Если вы выберете этот маршрут, имейте в виду, что это не так просто, как подсчет "свопов". Например, Mergesort является наихудшим случаем
O(N log N)
, но если он выполняется в списке, отсортированном в порядке убывания, он исправит всеN choose 2
инверсии. ЭтоO(N^2)
инверсии, исправленные вO(N log N)
операциях. Поэтому некоторые операции неизбежно должны корректировать более одной инверсии за раз. Вы должны быть осторожны с вашей реализацией. Примечание: вы можете сделать это соO(N log N)
сложностью, это просто сложно.Связанный: вычисление количества «инверсий» в перестановке
Подход 2 (Стохастик)
(i,j)
, гдеi != j
list[min(i,j)] < list[max(i,j)]
(0 или 1)N choose 2
Я бы лично использовал стохастический подход, если у вас нет требования к точности - хотя бы потому, что это так просто реализовать.
Если вы действительно хотите получить значение (
z'
) между-1
(отсортировано по убыванию) в1
(отсортировано по возрастанию), вы можете просто отобразить значение выше (z
), которое находится между0
(отсортировано по возрастанию) и1
(отсортировано по убыванию), в этот диапазон, используя эту формулу :источник
Традиционной мерой того, насколько отсортирован список (или другая последовательная структура), является количество инверсий.
Количество инверсий - это количество пар (a, b) -го индекса a <b И b
<<
a. Для этих целей<<
представляет собой любое отношение заказа, которое вы выбираете для вашего конкретного вида.Полностью отсортированный список не имеет инверсий, а полностью перевернутый список имеет максимальное количество инверсий.
источник
5 4 3 2 1
это полностью отсортировано, так как порядок не указан, но я педантичен :-)<
.n choose 2
.Вы можете использовать фактическую корреляцию.
Предположим, что каждому элементу в отсортированном списке вы назначаете целое число, начиная с нуля. Обратите внимание, что график индекса положения элементов в зависимости от ранга будет выглядеть как точки на прямой линии (корреляция 1,0 между позицией и рангом).
Вы можете вычислить корреляцию по этим данным. Для обратной сортировки вы получите -1 и так далее.
источник
Там были отличные ответы, и я хотел бы добавить математический аспект для полноты:
Вы можете измерить, насколько отсортирован список, измерив, насколько он соотнесен с отсортированным списком. Для этого вы можете использовать ранговую корреляцию (наиболее известной из которых является Спирмена ), которая в точности совпадает с обычной корреляцией, но она использует ранг элементов в списке вместо аналоговых значений своих элементов.
Существует множество расширений, например коэффициент корреляции (+1 для точной сортировки, -1 для точной инверсии)
Это позволяет вам иметь статистические свойства для этой меры, например, теорему о центральном пределе перестановок, которая позволяет узнать распределение этой меры для случайных списков.
источник
Помимо числа инверсий, для числовых списков можно представить среднеквадратичное расстояние от отсортированного состояния:
источник
Я не уверен в «лучшем» методе, но простым было бы сравнить каждый элемент с последующим, увеличив счетчик, если element2> element 1 (или что вы хотите проверить), а затем разделить на общее число элементов. Это должно дать вам процент.
источник
Я бы посчитал сравнения и разделил их на общее количество сравнений. Вот простой пример Python .
источник
Как насчет этого?
источник
Если вы возьмете свой список, вычислите ранги значений в этом списке и вызовете список рангов
Y
и другой список,X
который содержит целые числа от1
доlength(Y)
, вы можете получить именно ту меру сортировки, которую вы ищете, вычислив коэффициент корреляции ,r
между двумя списками.Для полностью отсортированного списка,
r = 1.0
для списка с обратной сортировкойr=-1.0
, а такжеr
различия между этими пределами для различной степени сортировки.Возможная проблема с этим подходом, в зависимости от приложения, состоит в том, что вычисление ранга каждого элемента в списке эквивалентно его сортировке, поэтому это операция O (n log n).
источник