BFPRT算法詳解

一、BFPRT算法原理

BFPRT算法(也稱為中位數的中位數算法)是基於快速排序算法基礎上的變種算法,用於尋找一個無序數組中第K小的數(或第K大的數)。

快速排序算法的核心思想是把一個無序數組的第一個數作為劃分元素,將數組分為兩個部分,左邊部分的數都小於劃分元素,右邊部分的數都大於劃分元素,然後分別對左邊和右邊的部分進行遞歸調用。但是快速排序算法的時間複雜度並不穩定,最壞情況下時間複雜度為O(n^2),這時候就需要使用BFPRT算法來解決這個問題。

BFPRT算法的核心思想是通過對數組進行特殊的劃分,確定第K小的數所在的區間。它首先將數組分成若干個5個元素一組的區間,對每個小區間進行排序,然後取出每個小區間的中位數,把這些中位數作為一個新的數組。

然後遞歸尋找這個數組的中位數(即第N/2小的數),假設這個數是x,那麼以x為中心,將數組分成兩部分,如果新數組中數的個數比x小,說明第K小的數在新數組後半部分,否則在新數組前半部分。對於所選擇的部分,再次遞歸調用進行查找,直到找到第K小的數。

int partition_median(int arr[], int left, int right) {
    // 將數組以每5個元素為一組分組,最後剩下的不足5個的單獨一組
    for (int i = left; i  right) {
            sub_right = right;
        }
        // 將小組進行插入排序,可以提高查找中位數的效率
        for (int j = i + 1; j = i && arr[k] > key) {
                arr[k + 1] = arr[k];
                k--;
            }
            arr[k + 1] = key;
        }
        // 將每個小組的中位數插入到數組的前面,方便後面進行遞歸查找
        int mid = (i + sub_right) / 2;
        int temp = arr[mid];
        arr[mid] = arr[left + (i - left) / 5];
        arr[left + (i - left) / 5] = temp;
    }
    // 遞歸查找所有中位數的中位數
    int median = (left + (right - left) / 10);
    if (left < right) {
        int pivotIndex = partition_median(arr, left, right);
        int i = partition(arr, left, right, pivotIndex);
        if (median  i) {
            // 第K小的數在數組右半部分
            return partition_median(arr, i + 1, right);
        }
        else {
            // 找到第K小的數,返回其值
            return arr[i];
        }
    }
    else {
        // 數組中只有一個元素,直接返回該元素的值
        return arr[left];
    }
}

二、BFPRT算法應用

1、尋找無序數組的中位數或第K小/大的數:使用定位排序算法,將數組劃分成若干個小組,對每個小組進行排序,然後將每個小組的中位數插入到一個新數組中,對新數組遞歸查找其中位數,以此確定第K小/大的數的位置。

int bfprt(int arr[], int left, int right, int k) {
    return partition_median(arr, left, right, k);
}

int main() {
    int arr[] = {3, 2, 1, 5, 6, 4};
    int k = 2; // 尋找第二小的數
    int n = sizeof(arr) / sizeof(arr[0]);
    int ans = bfprt(arr, 0, n - 1, k - 1);
    cout << "第" << k << "小的數是:" << ans << endl;
}

2、求無序數組的中位數與排序時間的實現:使用標準庫函數qsort排序,然後計算數組的中位數。這裡定義了一個類,其中構造函數中調用了qsort函數,並獲取數組的中位數,計算排序所需的時間。

class Median {
public:
    double median_;
    double sort_time_;

    Median(int arr[], int n) {
        clock_t start_time = clock();
        qsort(arr, n, sizeof(int), cmp);
        sort_time_ = (double)(clock() - start_time) / CLOCKS_PER_SEC;

        if (n % 2 == 0) {
            median_ = (double)(arr[n / 2 - 1] + arr[n / 2]) / 2.0;
        } else {
            median_ = (double)arr[n / 2];
        }
    }

    static int cmp(const void* a, const void* b) {
        return *(int*)a - *(int*)b;
    }
};

int main() {
    int arr[] = {3, 2, 1, 5, 6, 4};
    int n = sizeof(arr) / sizeof(arr[0]);
    int k = (n + 1) / 2;
    Median m(arr, n);
    cout << "排序所需時間: " << m.sort_time_ << "s" << endl;
    cout << "無序數組的中位數: " << m.median_ << endl;
}

三、BFPRT算法的優缺點

優點:

1、時間複雜度穩定,最壞情況下也只需要O(n)的時間複雜度。

2、與快速排序算法相比,BFPRT算法在大量數據的排序上表現更加優秀。

3、在尋找數組中第K小/大的數時,其所需時間不超過O(n)。

缺點:

1、在查找較小的K值時,效率可能會變慢。尤其是當K比較小,但N非常大的時候,會造成很大的時間開銷。

2、算法比較複雜,實現起來比較困難。

四、BFPRT算法的應用案例

1、使用BFPRT算法實現一道LeetCode的問題,尋找亂序數組中的第K大的元素。

class Solution {
public:
    int findKthLargest(vector& nums, int k) {
        int n = nums.size();
        int arr[n];
        for (int i = 0; i < n; i++) {
            arr[i] = nums[i];
        }
        int ans = bfprt(arr, 0, n - 1, n - k);
        return ans;
    }
};

int main() {
    Solution s;
    vector nums = {3,2,1,5,6,4};
    int k = 2;
    int ans = s.findKthLargest(nums, k);
    cout << "第" << k << "大的數是:" << ans << endl;
}

2、使用BFPRT算法對海量數據進行快速排序。

// 將數組劃分成若干個小區間,對每個小區間排序,然後獲取各個小區間的中位數即可
template 
void bfprt_sort(vector& nums, int left, int right, int k) {
    if (left >= right) {
        return;
    }
    if (right - left + 1 <= 5) {
        sort(nums.begin()+left, nums.begin()+right+1);
        return;
    }
    int pivotIndex = partition_median(nums, left, right);
    int index = partition(nums, left, right, pivotIndex);
    if (k  index) {
        bfprt_sort(nums, index+1, right, k);
    } else {
        return;
    }
}

template 
void big_data_sort(vector& nums) {
    int len = nums.size();
    int left = 0;
    int right = len - 1;
    int group_num = len / 5;
    int mod_num = len % 5;
    vector helper;
    for (int i = 0; i  0) {
        sort(nums.begin() + group_num*5, nums.begin() + group_num*5 + mod_num);
        helper.push_back(nums[group_num*5 + mod_num/2]);
    }
    // 新數組中的中位數即為整個數組的中位數
    int median_index = helper.size() / 2;
    bfprt_sort(helper, 0, helper.size()-1, median_index);
    T median = helper[median_index];
    // 使用整個數組的中位數進行劃分
    int pivot_index = partition_big_data(nums, left, right, median);
    int k = len / 2;
    if (len % 2 == 0) {
        bfprt_sort(nums, left, right, k-1);
    } else {
        bfprt_sort(nums, left, right, k);
    }
}

五、總結

BFPRT算法是一種常見的查找算法,其能夠在大量數據的排序問題中表現出較高的效率和穩定性。通過對數據進行特殊的劃分和查找,BFPRT算法能夠尋找無序數組中第K小/大的數,得到數組的中位數,或對大量數據進行快速排序等應用。

原創文章,作者:PTQS,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/144581.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
PTQS的頭像PTQS
上一篇 2024-10-25 13:53
下一篇 2024-10-25 13:53

相關推薦

  • 蝴蝶優化算法Python版

    蝴蝶優化算法是一種基於仿生學的優化算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化算法Python版…

    編程 2025-04-29
  • Python實現爬樓梯算法

    本文介紹使用Python實現爬樓梯算法,該算法用於計算一個人爬n級樓梯有多少種不同的方法。 有一樓梯,小明可以一次走一步、兩步或三步。請問小明爬上第 n 級樓梯有多少種不同的爬樓梯…

    編程 2025-04-29
  • AES加密解密算法的C語言實現

    AES(Advanced Encryption Standard)是一種對稱加密算法,可用於對數據進行加密和解密。在本篇文章中,我們將介紹C語言中如何實現AES算法,並對實現過程進…

    編程 2025-04-29
  • Harris角點檢測算法原理與實現

    本文將從多個方面對Harris角點檢測算法進行詳細的闡述,包括算法原理、實現步驟、代碼實現等。 一、Harris角點檢測算法原理 Harris角點檢測算法是一種經典的計算機視覺算法…

    編程 2025-04-29
  • 數據結構與算法基礎青島大學PPT解析

    本文將從多個方面對數據結構與算法基礎青島大學PPT進行詳細的闡述,包括數據類型、集合類型、排序算法、字符串匹配和動態規劃等內容。通過對這些內容的解析,讀者可以更好地了解數據結構與算…

    編程 2025-04-29
  • 瘦臉算法 Python 原理與實現

    本文將從多個方面詳細闡述瘦臉算法 Python 實現的原理和方法,包括該算法的意義、流程、代碼實現、優化等內容。 一、算法意義 隨着科技的發展,瘦臉算法已經成為了人們修圖中不可缺少…

    編程 2025-04-29
  • 神經網絡BP算法原理

    本文將從多個方面對神經網絡BP算法原理進行詳細闡述,並給出完整的代碼示例。 一、BP算法簡介 BP算法是一種常用的神經網絡訓練算法,其全稱為反向傳播算法。BP算法的基本思想是通過正…

    編程 2025-04-29
  • 粒子群算法Python的介紹和實現

    本文將介紹粒子群算法的原理和Python實現方法,將從以下幾個方面進行詳細闡述。 一、粒子群算法的原理 粒子群算法(Particle Swarm Optimization, PSO…

    編程 2025-04-29
  • Python回歸算法算例

    本文將從以下幾個方面對Python回歸算法算例進行詳細闡述。 一、回歸算法簡介 回歸算法是數據分析中的一種重要方法,主要用於預測未來或進行趨勢分析,通過對歷史數據的學習和分析,建立…

    編程 2025-04-28
  • 象棋算法思路探析

    本文將從多方面探討象棋算法,包括搜索算法、啟發式算法、博弈樹算法、神經網絡算法等。 一、搜索算法 搜索算法是一種常見的求解問題的方法。在象棋中,搜索算法可以用來尋找最佳棋步。經典的…

    編程 2025-04-28

發表回復

登錄後才能評論