انتخاب kامین عنصر کوچک در آرایه نامرتب — به زبان ساده

۱۰۳ بازدید
آخرین به‌روزرسانی: ۲۳ آذر ۱۳۹۸
زمان مطالعه: ۸ دقیقه
انتخاب kامین عنصر کوچک در آرایه نامرتب -- به زبان ساده

در این مطلب، روش نوشتن برنامه‌ای که kامین عنصر کوچک در آرایه نامرتب را پیدا کند، مورد بررسی قرار گرفته است. از همین روش می‌توان برای پیدا کردن kامین عنصر بزرگ در آرایه نامرتب نیز استفاده کرد. فرض می‌شود که یک آرایه و یک عدد K داده شده است. k کوچک‌تر از اندازه آرایه است. اکنون نیاز است که kاُمین عنصر کوچک‌تر در آرایه داده شده پیدا شود. همچنین، گفته شده که همه عناصر آرایه محدود هستند. شایان ذکر است، پیاده‌سازی روش آموزش داده شده در این مطلب، در زبان‌های برنامه‌نویسی گوناگون شامل «سی‌پلاس‌پلاس» (++C)، «جاوا» (Java)، «پایتون ۳» (Python 3) و «پی‌اچ‌پی» (PHP) انجام شده است. مثال زیر در این راستا قابل توجه است.

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) است. ایده این روش آن است که به طور تصادفی یک عنصر محوری (Pivot) انتخاب شود. برای پیاده‌سازی پارتیشن تصادفی شده، از تابع تصادفی rand()‎ برای تولید اندیس بین i و r، تعویض یک عنصر با اندیس تصادفی تولید شده با آخرین عنصر و در نهایت، فراخوانی فرایند تقسیم استاندارد که از آخرین عنصر به عنوان محور بهره می‌برد، استفاده شده است. در ادامه، یک پیاده‌سازی از «انتخاب سریع تصادفی» (Randomized QuickSelect) در زبان‌های برنامه‌نویسی گوناگون ارائه شده است.

برنامه انتخاب kامین عنصر کوچک در آرایه نامرتب در ++C

// C++ implementation of randomized quickSelect 
#include<iostream> 
#include<climits> 
#include<cstdlib> 
using namespace std; 
  
int randomPartition(int arr[], int l, int r); 
  
// This function returns k'th smallest element in arr[l..r] using 
// QuickSort based method. ASSUMPTION: 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 a random element and 
        // get position of pivot element in sorted array 
        int pos = randomPartition(arr, l, r); 
  
        // If position is same as k 
        if (pos-l == k-1) 
            return arr[pos]; 
        if (pos-l > k-1)  // If position is more, recur for left subarray 
            return kthSmallest(arr, l, pos-1, k); 
  
        // Else recur for right subarray 
        return kthSmallest(arr, pos+1, r, k-pos+l-1); 
    } 
  
    // If k is more than the number of elements in the array 
    return INT_MAX; 
} 
  
void swap(int *a, int *b) 
{ 
    int temp = *a; 
    *a = *b; 
    *b = temp; 
} 
  
// 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. This function is used by randomPartition() 
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; 
} 
  
// Picks a random pivot element between l and r and partitions 
// arr[l..r] around the randomly picked element using partition() 
int randomPartition(int arr[], int l, int r) 
{ 
    int n = r-l+1; 
    int pivot = rand() % n; 
    swap(&arr[l + pivot], &arr[r]); 
    return partition(arr, l, r); 
} 
  
// Driver program to test above methods 
int main() 
{ 
    int arr[] = {12, 3, 5, 7, 4, 19, 26}; 
    int n = sizeof(arr)/sizeof(arr[0]), k = 3; 
    cout << "K'th smallest element is " << kthSmallest(arr, 0, n-1, k); 
    return 0; 
}

برنامه انتخاب kامین عنصر کوچک در آرایه نامرتب در جاوا

// Java program to find k'th smallest element in expected 
// linear time 
class KthSmallst 
{ 
    // 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 a random element and 
            // get position of pivot element in sorted array 
            int pos = randomPartition(arr, l, r); 
  
            // If position is same as k 
            if (pos-l == k-1) 
                return arr[pos]; 
  
            // If position is more, recur for left subarray 
            if (pos-l > k-1) 
                return kthSmallest(arr, l, pos-1, k); 
  
            // Else recur for right subarray 
            return kthSmallest(arr, pos+1, r, k-pos+l-1); 
        } 
  
        // If k is more than number of elements in array 
        return Integer.MAX_VALUE; 
    } 
  
    // Utility method to swap arr[i] and arr[j] 
    void swap(int arr[], int i, int j) 
    { 
        int temp = arr[i]; 
        arr[i] = arr[j]; 
        arr[j] = temp; 
    } 
  
    // 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. This function 
    // is used by randomPartition() 
    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, j); 
                i++; 
            } 
        } 
        swap(arr, i, r); 
        return i; 
    } 
  
    // Picks a random pivot element between l and r and  
    // partitions arr[l..r] arount the randomly picked  
    // element using partition() 
    int randomPartition(int arr[], int l, int r) 
    { 
        int n = r-l+1; 
        int pivot = (int)(Math.random()) * (n-1); 
        swap(arr, l + pivot, r); 
        return partition(arr, l, r); 
    } 
  
    // Driver method to test above 
    public static void main(String args[]) 
    { 
        KthSmallst ob = new KthSmallst(); 
        int arr[] = {12, 3, 5, 7, 4, 19, 26}; 
        int n = arr.length,k = 3; 
        System.out.println("K'th smallest element is "+ 
                           ob.kthSmallest(arr, 0, n-1, k)); 
    } 
} 
/*This code is contributed by Rajat Mishra*/

برنامه انتخاب kامین عنصر کوچک در آرایه نامرتب در پایتون ۳

# Python3 implementation of randomized  
# quickSelect  
import random 
  
# This function returns k'th smallest  
# element in arr[l..r] using QuickSort 
# based method. ASSUMPTION: ELEMENTS 
# IN ARR[] ARE DISTINCT  
def kthSmallest(arr, l, r, k): 
      
    # If k is smaller than number of 
    # elements in array  
    if (k > 0 and k <= r - l + 1): 
          
        # Partition the array around a random  
        # element and get position of pivot  
        # element in sorted array  
        pos = randomPartition(arr, l, r)  
  
        # If position is same as k  
        if (pos - l == k - 1):  
            return arr[pos]  
        if (pos - l > k - 1): # If position is more,  
                            # recur for left subarray  
            return kthSmallest(arr, l, pos - 1, k)  
  
        # Else recur for right subarray  
        return kthSmallest(arr, pos + 1, r,  
                           k - pos + l - 1) 
  
    # If k is more than the number of  
    # elements in the array  
    return 999999999999
  
def swap(arr, a, b): 
    temp = arr[a] 
    arr[a] = arr[b] 
    arr[b] = temp 
  
# 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. This function 
# is used by randomPartition()  
def partition(arr, l, r): 
    x = arr[r] 
    i = l 
    for j in range(l, r): 
        if (arr[j] <= x): 
            swap(arr, i, j)  
            i += 1
    swap(arr, i, r)  
    return i 
  
# Picks a random pivot element between l and r  
# and partitions arr[l..r] around the randomly 
# picked element using partition()  
def randomPartition(arr, l, r): 
    n = r - l + 1
    pivot = int(random.random() % n)  
    swap(arr, l + pivot, r)  
    return partition(arr, l, r) 
  
# Driver Code 
if __name__ == '__main__': 
  
    arr = [12, 3, 5, 7, 4, 19, 26]  
    n = len(arr) 
    k = 3
    print("K'th smallest element is",  
           kthSmallest(arr, 0, n - 1, k)) 
  
# This code is contributed by PranchalK 

برنامه انتخاب kامین عنصر کوچک در آرایه نامرتب در #C

// C# program to find k'th smallest  
// element in expected linear time  
using System; 
  
class GFG  
{  
// 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 a  
        // random element and get position  
        // of pivot element in sorted array  
        int pos = randomPartition(arr, l, r);  
  
        // If position is same as k  
        if (pos-l == k - 1)  
            return arr[pos];  
  
        // If position is more, recur  
        // for left subarray  
        if (pos - l > k - 1)  
            return kthSmallest(arr, l, pos - 1, k);  
  
        // Else recur for right subarray  
        return kthSmallest(arr, pos + 1, r,  
                           k - pos + l - 1);  
    }  
  
    // If k is more than number of  
    // elements in array  
    return int.MaxValue;  
}  
  
// Utility method to swap arr[i] and arr[j]  
void swap(int []arr, int i, int j)  
{  
    int temp = arr[i];  
    arr[i] = arr[j];  
    arr[j] = temp;  
}  
  
// 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. This function  
// is used by randomPartition()  
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, j);  
            i++;  
        }  
    }  
    swap(arr, i, r);  
    return i;  
}  
  
// Picks a random pivot element between  
// l and r and partitions arr[l..r]  
// around the randomly picked element 
// using partition()  
int randomPartition(int []arr, int l, int r)  
{  
    int n = r - l + 1;  
    Random rnd = new Random(); 
    int rand = rnd.Next(0, 1); 
    int pivot = (int)(rand * (n - 1));  
    swap(arr, l + pivot, r);  
    return partition(arr, l, r);  
}  
  
// Driver Code 
public static void Main()  
{  
    GFG ob = new GFG();  
    int []arr = {12, 3, 5, 7, 4, 19, 26};  
    int n = arr.Length,k = 3;  
    Console.Write("K'th smallest element is "+  
            ob.kthSmallest(arr, 0, n - 1, k));  
}  
}  
  
// This code is contributed by 29AjayKumar 

برنامه انتخاب kامین عنصر کوچک در آرایه نامرتب در PHP

<?php 
// C# program to find k'th smallest  
// element in expected linear time  
  
// This function returns k'th smallest   
// element in arr[l..r] using QuickSort based method. 
// ASSUMPTION: ELEMENTS IN ARR[] ARE DISTINCT  
function 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 a random element and  
        // get position of pivot element in sorted array  
        $pos = randomPartition($arr, $l, $r);  
  
        // If position is same as k  
        if ($pos-$l == $k-1)  
            return $arr[$pos];  
              
        // If position is more, recur for left subarray  
        if ($pos-$l > $k-1) 
            return kthSmallest($arr, $l, $pos-1, $k);  
  
        // Else recur for right subarray  
        return kthSmallest($arr, $pos+1, $r, 
                            $k-$pos+$l-1);  
    }  
  
    // If k is more than the number of elements in the array  
    return PHP_INT_MAX;  
}  
  
function swap($a, $b)  
{  
    $temp = $a;  
    $a = $b;  
    $b = $temp;  
}  
  
// 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. 
// This function is used by randomPartition()  
function partition($arr, $l, $r)  
{  
    $x = $arr[$r]; 
    $i = $l;  
    for ($j = $l; $j <= $r - 1; $j++)  
    {  
        if ($arr[$j] <= $x)  
        {  
            list($arr[$i], $arr[$j])=array($arr[$j],$arr[$i]); 
            //swap(&arr[i], &arr[j]);  
            $i++;  
        }  
    }  
    list($arr[$i], $arr[$r])=array($arr[$r],$arr[$i]); 
    //swap(&arr[i], &arr[r]);  
    return $i;  
}  
  
// Picks a random pivot element between 
//  l and r and partitions arr[l..r] around  
// the randomly picked element using partition()  
function randomPartition($arr, $l, $r)  
{  
    $n = $r-$l+1;  
    $pivot = rand() % $n;  
      
    list($arr[$l + $pivot], $arr[$r]) =  
            array($arr[$r],$arr[$l + $pivot] ); 
      
    //swap(&arr[l + pivot], &arr[r]);  
    return partition($arr, $l, $r);  
}  
  
// Driver program to test above methods  
    $arr = array(12, 3, 5, 7, 4, 19, 260);  
    $n = sizeof($arr)/sizeof($arr[0]); 
    $k = 3;  
    echo "K'th smallest element is " , 
            kthSmallest($arr, 0, $n-1, $k);  
      
  
// This code is contributed by ajit.

خروجی قطعه کد بالا به صورت زیر است.

K'th smallest element is 5

پیچیدگی زمانی روش ارائه شده در بالا همچنان از درجه O(n2)‎ است. در بدترین حالت، تابع تصادفی همواره یک عنصر گوشه‌ای را انتخاب می‌کند. پیچیدگی زمانی مورد انتظار از QuickSelect از درجه (O(n است. فرض بر این است که در تحلیل‌ها، «مولد اعداد تصادفی» (Random Number Generator) دارای احتمال یکسانی برای تولید اعداد در رنج ورودی است.

اگر نوشته بالا برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

^^

بر اساس رای ۴ نفر
آیا این مطلب برای شما مفید بود؟
شما قبلا رای داده‌اید!
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
GeeksforGeeks

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *