線性時間選擇

其實就是算法書上的一個問題實現,複雜度O(n)。

給定線性序集中n個元素和一個整數k,1<=k<=n,要求找出這n個元素中第k小的元素,即如果將這n個元素依次線性排序時,排在第k個位置的元素即爲要找的元素。當k-1時,就是要找的最小元素;當k=n時,就是要找的最大元素;當k=(n+1)/2,稱爲中位數。

#include <iostream>
#define LENGTH 16
using namespace std;

void exswap(int& i, int& j)
{
    int n;
    n = i;
    i = j;
    j = n;
}

int Partition(int a[], int p, int r, int x)
{
    //將小於x的元素放到左邊
    //反之放到右邊
    int i = p - 1;
    for (int j = p; j <= r - 1; j++) {
        if (a[j] <= x) {
            i++;
            exswap(a[i], a[j]);
        }
    }
    exswap(a[i + 1], a[r]);
    return i + 1;
}

void QuickSort(int a[], int p, int r)
{
    if (p < r) {
        int q = Partition(a, p, r, a[r]);
        QuickSort(a, p, q - 1);
        QuickSort(a, q + 1, r);
    }
}

int Select(int a[], int p, int r, int k)
{
    if (r - p < 15) //小於閾值時直接使用快排
    {
        QuickSort(a, p, r);
        return a[p + k - 1];
    }
    for (int i = 0; i <= (r - p - 4) / 5; i++) {
        QuickSort(a, p + 5 * i, p + 5 * i + 4); //範圍內數字進行O(1)快排
        exswap(a[p + i], a[p + 5 * i + 2]); //這裏是第k小元素與a[p+i]交換位置
    }
    //查找中位數的中位數
    int x = Select(a, p, p + (r - p - 4) / 5, (r - p - 4) / 10);
    int i = Partition(a, p, r, x), j = i - p + 1;
    if (k <= j)
        return Select(a, p, i, k);
    else
        return Select(a, i + 1, r, k - j);
}

int main()
{
    int test[LENGTH] = { 1, 0, 11, 2, 14, 1523, 233, 123, 11, 5, 4, 12, 7, 6, 9, 8 };
    int k, x;
    cout << "Number of k?" << endl;
    cin >> k;
    x = Select(test, 0, LENGTH - 1, k);
    cout << "Is " << x << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章