Сортировка выбором

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

Шаблон:Алгоритм Сортировка выбором (англ. selection sort) — алгоритм сортировки. Может быть как устойчивый, так и неустойчивый. На массиве из <math>n</math> элементов имеет время выполнения в худшем, среднем и лучшем случае <math>O(n^2)</math>, предполагая что сравнения делаются за постоянное время.

Алгоритм без дополнительного выделения памяти

Сортировка выбором

Шаги алгоритма:

  1. Находим номер минимального значения в текущем списке.
  2. Производим обмен этого значения со значением первой неотсортированной позиции (обмен не нужен, если минимальный элемент уже находится на данной позиции).
  3. Теперь сортируем хвост списка, исключив из рассмотрения уже отсортированные элементы.

Реализация алгоритма на языках программирования

Далее находится пример неустойчивой реализации данного алгоритма:

<source lang="cpp" line="1"> template <typename type_arr> void selection_sort(type_arr *arr, int size) {

   for (int i = 0; i < size - 1; i++)
   {
       int min_index = i;
       for (int j = i + 1; j < size; j++)
       {
           if (arr[j] < arr[min_index])
           {
               min_index = j;
           }
       }
       if (min_index != i)
       {
           swap(arr[i], arr[min_index]);
       }
   }

} </source>

<source lang="csharp" line="1"> public static IList<T> Selection<T>(IList<T> list) where T : IComparable<T> {

   for (int i = 0; i < list.Count - 1; ++i)
   {
       int min = i;
       for (int j = i + 1; j < list.Count; ++j)
       {
       	if (list[j].CompareTo(list[min]) < 0)
           {
               min = j;
           }
       }
       
       var dummy = list[i];
       list[i] = list[min];
       list[min] = dummy;
   }
   
   return list;

} </source>

<source lang="plsql" line="1"> type sort_choice_list is table of integer index by binary_integer;


function SORT_CHOICE return sort_choice_list

 IS
   list sort_choise_list;
   l_min pls_integer;
   l_dummy pls_integer;
 begin 
 
     for n in 1..100 loop
       list(n):=dbms_random.random; --инициализация массива случайными числами
     end loop;
     
     for i in list.first..list.last loop
          l_min:=i;
          for j in (i + 1)..list.last loop
               if (list(j) < list(l_min)) then
                   l_min := j;
               end if;
           end loop;
           l_dummy:=list(i);
           list(i):=list(l_min);
           list(l_min) := l_dummy;
     end loop;
        
   return list;
     

end SORT_CHOICE; </source>

<source lang="java" line="1"> public static void selectionSort(int [] arr) { int n = arr.length; for(int i = 0; i<n-1; i++) { int minIndex = i; for(int j=i+1; j<n; j++) { if(arr[j]<arr[minIndex]) { minIndex = j; } } if(minIndex!=i) swap(arr,i,minIndex);

} }

</source>

<syntaxhighlight lang="ruby" line="1" start="1"> def selection_sort(array) for min in 0..array.count-2 least = min for j in (min + 1)..array.count-1 if array[j] < array[least] least = j end end temp = array[min] array[min] = array[least] array[least] = temp end end </syntaxhighlight>

<syntaxhighlight lang="swift" line="1" start="1"> func selectionSort<Element>(_ array: inout Array<Element>) where Element: Comparable { for min in 0..<array.count - 1 { for j in min..<array.count { if array[j] < array[min] { let temp = array[min] array[min] = array[j] array[j] = temp } } } } </syntaxhighlight>

<syntaxhighlight lang=pascal line="1"> begin

 var a := ArrRandom;
 a.Println;
 for var i:=0 to a.High do
    Swap(a[i],a[i+a[i:].IndexMin]);
 a.Println;

end </syntaxhighlight>

<source lang="python" line="1"> def select_sort(A):

   for i in range(len(A) - 1):
       min_index = i
       for k in range(i + 1, len(A)):
           if A[k] < A[min_index]:
               A[k], A[min_index] = A[min_index], A[k]
   return A
   
   

</source>

<syntaxhighlight lang="go" line="1"> func selectionSort(nums []int) {

   n := len(nums)
   for i := 0; i < n; i++ {
       min := i 
       for j := i + 1; j < n; j++ {
           if nums[j] < nums[min] {
               min = j
           }
       }
       nums[i], nums[min] = nums[min], nums[i]
   }

} </syntaxhighlight>

<syntaxhighlight lang="rust" line="1"> fn selection_sort<T: Ord>(array: &mut [T]) {

   let n = array.len();
   for i in 0..n {
       let mut min_index = i;
       for j in i + 1..n {
           if array[min_index] > array[j] {
               min_index = j;
           }
       }
       if min_index != i {
           array.swap(i, min_index);
       }
   }

} </syntaxhighlight>

Почему такая реализация неустойчива?

Покажем, почему данная реализация является неустойчивой.

Рассмотрим следующий массив из элементов, каждый из которых имеет два поля. Сортировка идет по первому полю.
Массив до сортировки: { (2, a), (2, b), (1, a) }
Уже после первой итерации внешнего цикла будем иметь отсортированную последовательность: { (1, a), (2, b), (2, a) }

Теперь заметим, что взаимное расположение элементов (2, a) и (2, b) изменилось.
Таким образом, рассматриваемая реализация является неустойчивой.

Сравнение с другими алгоритмами сортировки

Так как после каждого прохода по внутреннему циклу делается только один обмен, то общее число обменов равно <math>n-1</math>, что в <math>n/2</math> раз меньше, чем в сортировке пузырьком.
Число проходов по внутреннему циклу равно <math>n-1</math> даже в случае сортировки частично или полностью отсортированного массива.

  • Число сравнений в теле цикла равно <math>(n-1)*n/2</math>.
  • Число сравнений в заголовках циклов <math>(n-1)*n/2</math>.
  • Число сравнений перед операцией обмена <math>n-1</math>.
  • Суммарное число сравнений <math>n^2-1</math>.
  • Число обменов <math>n-1</math>.

Время сортировки 10000 коротких целых чисел на одном и том же программно-аппаратном комплексе сортировкой выбором составило ≈ 40 секунд, а ещё более улучшенной сортировкой пузырьком ≈ 30 секунд.
Пирамидальная сортировка сильно улучшает базовый алгоритм, используя структуру данных «куча» для ускорения нахождения и удаления минимального элемента. Существует также двунаправленный вариант сортировки методом выбора, в котором на каждом проходе отыскиваются и устанавливаются на свои места и минимальное, и максимальное значения.

Литература

См. также

Ссылки

Шаблон:Wikibooks

Шаблон:Алгоритмы сортировки