在期望线性时间内做出选择

    对于求一个数中集合的最大最小值问题可以在线性时间内解决问题,因为对于集合一次扫描就可以做出决定。而如何找出 0 ~ k中的第n大的数呢?可能对于大多数情况来说我们可以对集合进行排序,效率越高越好,再找出第n大的数。这样的时间消耗就是排序的时间消耗。

       为了在期望线性时间内做出选择,算法导论中给出了一种随机选择的算法,关于渐进时间为线性的证明书中有。它的思想主要是从随机快速排序算法而来,然而它每次只对快速排序划分的一边进行处理,有点类似二分法(二分快,但其必须是有序的哦)。

      过程是对集合进行随机的划分,而对于中枢值来说一次划分就可以找到其正确的位置,我们将中枢值所在位置与要找的n进行对比,如果小于中枢值的位置,就对比中枢值大的部分进行递归随机选择。递归结束的条件是被划分的区间的大小为1,或者中枢值所在的位置就是n。

      选择算法之所以有线性的运行时间,是因为它们没有进行排序。

以下是C实现

int getkthnum(int* intarray, int p, int r, int kth)
{
    int q;
    int k;
    if(p == r)
        return intarray[p];

    q = randompartion(intarray, p, r);
    k = q + 1;
    if (k == kth)
        return intarray[k - 1];
    else
    {
        if (k < kth)
            return getkthnum(intarray, q + 1 , r, kth);
        else
            return getkthnum(intarray, p, q - 1, kth);
    }
}

int randompartion(int* a, int startpos, int endpos)
{
    assert(startpos < endpos);
    int size = endpos - startpos + 1;
    int randompos = 0;
    //i :first big number j :first undetected number
    int i, j;
    int pivot;
    srand(time(0));
    randompos = rand() % size;
    swap(a, endpos, startpos + randompos);
    i = startpos;
    j = startpos;
    pivot = a[endpos];
    while (j != endpos)
    {
        if (a[j] < pivot)
        {
            swap(a, i, j);
            i++;
            j++;
        }
        else
            j++;
    }
    swap(a, i, endpos);
    return i;
}

void swap(int* a, int pos1, int pos2)
{
    int buffer;
    buffer = a[pos1];
    a[pos1] = a[pos2];
    a[pos2] = buffer; 
}



void main()
{
    int len, startpos, endpos;
    int a[100];
    int i;
    int k;
    int number;
    printf("input your number count less than 100 and startposition and end position\n");
    scanf("%d%d%d", &len, &startpos, &endpos);
    printf("input your numbers less than 100....\n");
    for (i = 0; i != len; i++)
        scanf("%d", &a[i]);
    printf("input the kth number you want to get\n");
    scanf("%d", &k);
    number = getkthnum(a, startpos, endpos, k);
    printf("the kth number you want to get is %d\n", number);
}
posted @ 2012-09-23 16:27  answer0107  阅读(112)  评论(0)    收藏  举报