📜  QuickSelect(一个简单的迭代实现)

📅  最后修改于: 2021-05-04 11:22:00             🧑  作者: Mango

快速选择是一种选择算法,用于在无序列表中找到第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

QuickSelect算法基于QuickSort。不同之处在于,它只对包含第k个最小元素的部分重复出现,而不是对两侧都重复出现。逻辑很简单,如果分区元素的索引大于k,则针对左部分递归。如果index与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 < pivotIndex
      right := pivotIndex - 1
   else
      left := pivotIndex + 1

我们已经讨论了QuickSelect的递归实现。在本文中,我们将讨论简单的迭代实现。

C++
// CPP program for iterative implementation of QuickSelect
#include 
using namespace std;
  
// Standard Lomuto partition function
int partition(int arr[], int low, int high)
{
    int pivot = arr[high];
    int i = (low - 1);
    for (int j = low; j <= high - 1; j++) {
        if (arr[j] <= pivot) {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[high]);
    return (i + 1);
}
  
// Implementation of QuickSelect
int kthSmallest(int a[], int left, int right, int k)
{
  
    while (left <= right) {
  
        // Partition a[left..right] around a pivot
        // and find the position of the pivot
        int pivotIndex = partition(a, left, right);
  
        // If pivot itself is the k-th smallest element
        if (pivotIndex == k - 1)
            return a[pivotIndex];
  
        // If there are more than k-1 elements on
        // left of pivot, then k-th smallest must be
        // on left side.
        else if (pivotIndex > k - 1)
            right = pivotIndex - 1;
  
        // Else k-th smallest is on right side.
        else
            left = pivotIndex + 1;
    }
    return -1;
}
  
// Driver program to test above methods
int main()
{
    int arr[] = { 10, 4, 5, 8, 11, 6, 26 };
    int n = sizeof(arr) / sizeof(arr[0]);
    int k = 5;
    cout << "K-th smallest element is "
         << kthSmallest(arr, 0, n - 1, k);
    return 0;
}


Java
// Java program for iterative implementation
// of QuickSelect
class GFG 
{
      
    // Standard Lomuto partition function 
    static int partition(int arr[], 
                         int low, int high) 
    { 
        int temp;
        int pivot = arr[high]; 
        int i = (low - 1); 
        for (int j = low; j <= high - 1; j++) 
        { 
            if (arr[j] <= pivot) 
            { 
                i++; 
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            } 
        } 
          
            temp = arr[i + 1];
            arr[i + 1] = arr[high];
            arr[high] = temp;
              
        return (i + 1); 
    } 
      
    // Implementation of QuickSelect 
    static int kthSmallest(int a[], int left,
                           int right, int k) 
    { 
        while (left <= right) 
        { 
      
            // Partition a[left..right] around a pivot 
            // and find the position of the pivot 
            int pivotIndex = partition(a, left, right); 
      
            // If pivot itself is the k-th smallest element 
            if (pivotIndex == k - 1) 
                return a[pivotIndex]; 
      
            // If there are more than k-1 elements on 
            // left of pivot, then k-th smallest must be 
            // on left side. 
            else if (pivotIndex > k - 1) 
                right = pivotIndex - 1; 
      
            // Else k-th smallest is on right side. 
            else
                left = pivotIndex + 1; 
        } 
        return -1; 
    } 
      
    // Driver Code
    public static void main (String[] args) 
    { 
        int arr[] = { 10, 4, 5, 8, 11, 6, 26 }; 
        int n = arr.length; 
        int k = 5; 
        System.out.println("K-th smallest element is " + 
                         kthSmallest(arr, 0, n - 1, k)); 
    } 
}
  
// This code is contributed by AnkitRai01


Python3
# Python3 program for iterative implementation
# of QuickSelect 
  
# Standard Lomuto partition function 
def partition(arr, low, high) : 
  
    pivot = arr[high] 
    i = (low - 1) 
    for j in range(low, high) : 
        if arr[j] <= pivot : 
            i += 1
            arr[i], arr[j] = arr[j], arr[i] 
          
    arr[i + 1], arr[high] = arr[high], arr[i + 1] 
    return (i + 1) 
  
# Implementation of QuickSelect 
def kthSmallest(a, left, right, k) : 
  
    while left <= right : 
  
        # Partition a[left..right] around a pivot 
        # and find the position of the pivot 
        pivotIndex = partition(a, left, right) 
  
        # If pivot itself is the k-th smallest element 
        if pivotIndex == k - 1 : 
            return a[pivotIndex] 
  
        # If there are more than k-1 elements on 
        # left of pivot, then k-th smallest must be 
        # on left side. 
        elif pivotIndex > k - 1 :
            right = pivotIndex - 1
  
        # Else k-th smallest is on right side. 
        else :
            left = pivotIndex + 1
      
    return -1
  
# Driver Code
arr = [ 10, 4, 5, 8, 11, 6, 26 ] 
n = len(arr) 
k = 5
print("K-th smallest element is", 
       kthSmallest(arr, 0, n - 1, k)) 
  
# This code is contributed by
# divyamohan123


C#
// C# program for iterative implementation
// of QuickSelect
using System;
                      
class GFG 
{
      
    // Standard Lomuto partition function 
    static int partition(int []arr, 
                         int low, int high) 
    { 
        int temp;
        int pivot = arr[high]; 
        int i = (low - 1); 
        for (int j = low; j <= high - 1; j++) 
        { 
            if (arr[j] <= pivot) 
            { 
                i++; 
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            } 
        } 
          
        temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;
              
        return (i + 1); 
    } 
      
    // Implementation of QuickSelect 
    static int kthSmallest(int []a, int left,
                           int right, int k) 
    { 
        while (left <= right) 
        { 
      
            // Partition a[left..right] around a pivot 
            // and find the position of the pivot 
            int pivotIndex = partition(a, left, right); 
      
            // If pivot itself is the k-th smallest element 
            if (pivotIndex == k - 1) 
                return a[pivotIndex]; 
      
            // If there are more than k-1 elements on 
            // left of pivot, then k-th smallest must be 
            // on left side. 
            else if (pivotIndex > k - 1) 
                right = pivotIndex - 1; 
      
            // Else k-th smallest is on right side. 
            else
                left = pivotIndex + 1; 
        } 
        return -1; 
    } 
      
    // Driver Code
    public static void Main (String[] args) 
    { 
        int []arr = { 10, 4, 5, 8, 11, 6, 26 }; 
        int n = arr.Length; 
        int k = 5; 
        Console.WriteLine("K-th smallest element is " + 
                        kthSmallest(arr, 0, n - 1, k)); 
    } 
}
  
// This code is contributed by 29AjayKumar


输出:
K-th smallest element is 10