Алгоритм швидкого вибору

Швидкий вибір це алгоритм вибору для пошуку k-го найменшого елемента в невпорядкованому списку. Це пов'язано з швидке сортування алгоритм сортування.
приклади:

Input: arr[] = {7, 10, 4, 3, 20, 15} k = 3 Output: 7 Input: arr[] = {7, 10, 4, 3, 20, 15} k = 4 Output: 10 

Алгоритм схожий на QuickSort. Різниця полягає в тому, що замість повторення для обох сторін (після знаходження опори), воно повторюється лише для частини, яка містить k-й найменший елемент. Логіка проста: якщо індекс розділеного елемента більше k, то ми повторюємо для лівої частини. Якщо індекс дорівнює k, ми знайшли k-й найменший елемент і повертаємося. Якщо індекс менше k, то повторюємо для правої частини. Це зменшує очікувану складність з O(n log n) до O(n), у найгіршому випадку O(n^2).

function quickSelect(list, left, right, k) if left = right return list[left] Select a pivotIndex between left and right pivotIndex := partition(list, left, right, pivotIndex) if k = pivotIndex return list[k] else if k  C++14       // CPP program for implementation of QuickSelect  #include  using namespace std;    // Standard partition process of QuickSort().  // It considers the last element as pivot  // and moves all smaller element to left of  // it and greater elements to right  int partition(int arr[], int l, int r)  {   int x = arr[r], i = l;   for (int j = l; j  <= r - 1; j++) {   if (arr[j]  <= x) {   swap(arr[i], arr[j]);   i++;   }   }   swap(arr[i], arr[r]);   return i;  }    // This function returns k'th smallest  // element in arr[l..r] using QuickSort  // based method. ASSUMPTION: ALL ELEMENTS  // IN ARR[] ARE DISTINCT  int kthSmallest(int arr[], int l, int r, int k)  {   // If k is smaller than number of   // elements in array   if (k>0 && k <= r - l + 1) {     // Partition the array around last   // element and get position of pivot   // element in sorted array   int index = partition(arr, l, r);     // If position is same as k   if (index - l == k - 1)   return arr[index];     // If position is more, recur   // for left subarray   if (index - l>k - 1) повертає kthSmallest(arr, l, index - 1, k);     // Інакше повторюється для правого підмасиву return kthSmallest(arr, index + 1, r, k - index + l - 1);   } // Якщо k перевищує кількість // елементів у масиві return INT_MAX;  } // Програма драйвера для перевірки вищевказаних методів int main() { int arr[] = { 10, 4, 5, 8, 6, 11, 26 };   int n = sizeof(arr) / sizeof(arr[0]);   int k = 3;   cout < < 'K-th smallest element is '   < < kthSmallest(arr, 0, n - 1, k);   return 0;  }   Java       // Java program of Quick Select  import java.util.Arrays;    class GFG {     // partition function similar to quick sort   // Considers last element as pivot and adds   // elements with less value to the left and   // high value to the right and also changes   // the pivot position to its respective position   // in the final array.   public static int partition(int[] arr, int low,   int high)   {   int pivot = arr[high], pivotloc = low;   for (int i = low; i  <= high; i++) {   // inserting elements of less value   // to the left of the pivot location   if (arr[i]   int temp = arr[i];   arr[i] = arr[pivotloc];   arr[pivotloc] = temp;   pivotloc++;   }   }     // swapping pivot to the final pivot location   int temp = arr[high];   arr[high] = arr[pivotloc];   arr[pivotloc] = temp;     return pivotloc;   }     // finds the kth position (of the sorted array)   // in a given unsorted array i.e this function   // can be used to find both kth largest and   // kth smallest element in the array.   // ASSUMPTION: all elements in arr[] are distinct   public static int kthSmallest(int[] arr, int low,   int high, int k)   {   // find the partition   int partition = partition(arr, low, high);     // if partition value is equal to the kth position,   // return value at k.   if (partition == k - 1)   return arr[partition];     // if partition value is less than kth position,   // search right side of the array.   else if (partition 1)   return kthSmallest(arr, partition + 1, high, k);     // if partition value is more than kth position,   // search left side of the array.   else  return kthSmallest(arr, low, partition - 1, k);   }     // Driver Code   public static void main(String[] args)   {   int[] array = new int[] { 10, 4, 5, 8, 6, 11, 26 };   int[] arraycopy   = new int[] { 10, 4, 5, 8, 6, 11, 26 };     int kPosition = 3;   int length = array.length;     if (kPosition>length) { System.out.println('Індекс поза межами');   } else { // знайти k-те найменше значення System.out.println( 'K-й найменший елемент у масиві : ' + kthSmallest(arraycopy, 0, length - 1, kPosition));   } } } // Цей код створено Saiteja Pamulapati Python3 # Програма Python3 Quick Select # Стандартний процес розділення QuickSort().  # Він розглядає останній елемент як опорний # і переміщує всі менші елементи # ліворуч від нього, а більші елементи - праворуч def partition(arr, l, r): x = arr[r] i = l for j in range(l, r): якщо arr[j] <= x:   arr[i], arr[j] = arr[j], arr[i]   i += 1    arr[i], arr[r] = arr[r], arr[i]   return i    # finds the kth position (of the sorted array)  # in a given unsorted array i.e this function  # can be used to find both kth largest and  # kth smallest element in the array.  # ASSUMPTION: all elements in arr[] are distinct  def kthSmallest(arr, l, r, k):     # if k is smaller than number of   # elements in array   if (k>0 і k <= r - l + 1):     # Partition the array around last   # element and get position of pivot   # element in sorted array   index = partition(arr, l, r)     # if position is same as k   if (index - l == k - 1):   return arr[index]     # If position is more, recur   # for left subarray   if (index - l>k - 1): return kthSmallest(arr, l, index - 1, k) # Else recur для правого підмасиву return kthSmallest(arr, index + 1, r, k - index + l - 1) print('Index out of bound') # Код драйвера arr = [ 10, 4, 5, 8, 6, 11, 26 ] n = len(arr) k = 3 print('K-й найменший елемент є ', end = ' ') print(kthSmallest(arr, 0, n - 1, k)) # Цей код створено Muskan Kalra.   C# // C# програма Quick Select using System;    class GFG { // функція розділення, подібна до швидкого сортування // Вважає останній елемент опорним і додає // елементи з меншим значенням ліворуч і // з високим значенням праворуч, а також змінює // позицію опори на відповідну позицію / / в масиві тільки для читання.   static int partitions(int []arr,int low, int high) { int pivot = arr[high], pivotloc = low, temp;   for (int i = low; i <= high; i++)   {   // inserting elements of less value   // to the left of the pivot location   if(arr[i]   {   temp = arr[i];   arr[i] = arr[pivotloc];   arr[pivotloc] = temp;   pivotloc++;   }   }     // swapping pivot to the readonly pivot location   temp = arr[high];   arr[high] = arr[pivotloc];   arr[pivotloc] = temp;     return pivotloc;   }     // finds the kth position (of the sorted array)   // in a given unsorted array i.e this function   // can be used to find both kth largest and   // kth smallest element in the array.   // ASSUMPTION: all elements in []arr are distinct   static int kthSmallest(int[] arr, int low,   int high, int k)   {   // find the partition   int partition = partitions(arr,low,high);     // if partition value is equal to the kth position,   // return value at k.   if(partition == k)   return arr[partition];     // if partition value is less than kth position,   // search right side of the array.   else if(partition   return kthSmallest(arr, partition + 1, high, k );     // if partition value is more than kth position,   // search left side of the array.   else  return kthSmallest(arr, low, partition - 1, k );   }     // Driver Code   public static void Main(String[] args)   {   int[] array = {10, 4, 5, 8, 6, 11, 26};   int[] arraycopy = {10, 4, 5, 8, 6, 11, 26};     int kPosition = 3;   int length = array.Length;     if(kPosition>length) { Console.WriteLine('Індекс поза межами');   } else { // знайти k-те найменше значення Console.WriteLine('K-й найменший елемент у масиві : ' + kthSmallest(arraycopy, 0, length - 1, kPosition - 1));   } } } // Цей код створено 29AjayKumar Javascript // Javascript-програма Quick Select // функція розділення, подібна до швидкого сортування // Вважає останній елемент опорним і додає // елементи з меншим значенням ліворуч і // великим значенням вправо, а також змінює // позицію опори на відповідну позицію // в остаточному масиві.  функція _partition(arr, low, high) { let pivot = arr[high], pivotloc = low;   для (нехай i = низький; i <= high; i++)   {     // inserting elements of less value   // to the left of the pivot location   if (arr[i]   {   let temp = arr[i];   arr[i] = arr[pivotloc];   arr[pivotloc] = temp;   pivotloc++;   }   }     // swapping pivot to the final pivot location   let temp = arr[high];   arr[high] = arr[pivotloc];   arr[pivotloc] = temp;     return pivotloc;  }    // finds the kth position (of the sorted array)   // in a given unsorted array i.e this function   // can be used to find both kth largest and   // kth smallest element in the array.   // ASSUMPTION: all elements in arr[] are distinct  function kthSmallest(arr, low, high, k)  {     // find the partition   let partition = _partition(arr, low, high);     // if partition value is equal to the kth position,   // return value at k.   if (partition == k - 1)   return arr[partition];     // if partition value is less than kth position,   // search right side of the array.   else if (partition   return kthSmallest(arr, partition + 1, high, k);     // if partition value is more than kth position,   // search left side of the array.   else  return kthSmallest(arr, low, partition - 1, k);  }    // Driver Code  let array = [ 10, 4, 5, 8, 6, 11, 26];  let arraycopy = [10, 4, 5, 8, 6, 11, 26 ];  let kPosition = 3;  let length = array.length;    if (kPosition>length) { document.write('Індекс поза межами ');  } else { // знайти k-те найменше значення document.write( 'K-й найменший елемент у масиві: ' + kthSmallest(arraycopy, 0, length - 1, kPosition)+' ');  } // Цей код створено rag2127. Результат: K-й найменший елемент – це 6. Важливі моменти: як і швидке сортування, на практиці це швидко, але має низьку продуктивність у найгіршому випадку. Він використовується в Процес розділення такий самий, як QuickSort, лише відрізняється рекурсивний код. Існує алгоритм, який знаходить k-й найменший елемент в O(n) у найгіршому випадку, але QuickSelect у середньому працює краще.    Пов’язана функція C++: std::nth_element у C++