求第K大数的递归函数方法

对于求第K大元素,也可以应用到求中位数.

以下也是基于求中位数对该函数进行演示。

主要思路:

先从数组左边扫描,如果发现了比e小的元素则暂停;再从数组右边扫描,遇到大于等于e的元素则暂停。此时左右两个暂停点的元素是错位的,把他们交换一下。然后从左右暂停点开始重复上述步骤,直到左右扫描在中间某处相会。此时相会的位置就是基准e把两个集合分开的位置,把e换到这个位置上,S1中元素就被放在e的左边,S2中的元素就被放在e的右边。

#include <stdio.h>

void Swap(int* x, int* y)
{
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

int FindKthLargest(int S[], int K, int Left, int Right)
{
    int e = S[Left]; //取第一个元素为基准
    int L = Left, R = Right;

    while (1) //将序列中比基准大的一道基准左边,小的移到右边
    {
        while ((Left <= Right) && (e <= S[Left]))
            Left++;
        while ((Left < Right) && (e > S[Right]))
            Right--;
        if (Left < Right)
            Swap(&S[Left], &S[Right]);
        else
            break;
    }
    Swap(&S[Left - 1], &S[L]);                    //将基准换到两集合之间
    if ((Left - L - 1) >= K)                      //(Left-L-1)表示了集合S1的大小
        return FindKthLargest(S, K, L, Left - 2); //在集合S1中查找
    else if ((Left - L - 1) < K - 1)              //在集合S2中查找
        return FindKthLargest(S, K - (Left - L - 1) - 1, Left, R);
    else
        return e; //找到了,返回e
}

int Median(int S[], int N)
{
    return FindKthLargest(S, (N + 1) / 2, 0, N - 1);
}

int main(void)
{
    int a[] = { 3, 5, 4, 7, 2, 1, 6 };//示例数组
    int i;
    i = Median(a, 7);
    printf("中位数为:%d
", i);
    return 0;
}
经验分享 程序员 微信小程序 职场和发展