查找第K小元素(C语言版)

       今天在看《算法:C语言实现》时,在高速排序那一章最后一节讲述了利用高速排序的思想。高速排序每次划分后在枢轴的左边的元素都比枢轴小(或相等),在枢轴右边的数都比枢轴大(或相等)。而划分后枢轴本身就放在了(有序时)它自身应该在的位置,在每次划分后推断枢轴下标和k的大小就能够高速找出数列中第k小的数了。

       看完之后。我想既然利用高速排序的思想能够非常快的找到第k小的数,那么能不能利用计数排序的思想来查找第k小的数呢。细致一想,全然能够!计数排序是利用一个计数数组C来记录待排序数组中各个不同数值出现的次数,然后通过一次遍历计数数组C,利用C[i] += C[i-1]就能够得到小于等于数值i的元素的个数,然后依照C[i]就能够把待排序数组中值为i的数放到它应该在的位置上。那怎么利用这个计数数组C呢?在对计数数组进行遍历后(运行C[i] += C[i-1]),C[i]代表待排序数组中值小于等于i的元素个数,而C[i-1]代表值小于等于i-1的元素个数,假设 C[i-1] < k而且k <= C[i],那么待排序数组中第k小的数必然就是值为i的数!查找就能够结束了。所以仅仅须要找到第一个满足条件k <= C[i]的i就可以。

       在说详细的算法之前先约定第k小的数为在数列有序时从0開始的第k-1个数。也就是k>0。

       既然谈到关于查找第k小元素的问题,那么就干脆把我近期学习到的和自己想到的方法写下来和大家一起交流。

       以下先从最简单的算法讲起:


一、先排序整个数列然后取第k-1个数

       这种方法简单粗暴,先把数列按从小到大的方式排列。就能够轻松得到第k-1个数了,可是,这种方法让整个数列都有序了,做了太多的无用功。


二、利用选择排序

       第一个方法简单直接,可是因为我们仅仅须要得到的是整个数列的第k小的数,所以,我们能够用选择排序的思想:选择排序每一次遍历数列都从剩余N-i个数中选取一个最小的数和前面的第i个值进行交换,直到i等于N-1时整个数列就是有序的了。

对于选取第k小的数的问题,我们仅仅须要进行k趟选择排序就能够得到第k小的数了。

代码例如以下:

//利用选择排序的思想,找k趟就能找到第k小的元素
void selectSortSearch(int array[], int size, int k)
{
    int minIndex;
    int i = 0;
    int j = 0;
    for (i = 0; i < k; ++i) {
        minIndex = i;
        for (j = i + 1; j < size; ++j) {
            if (array[j] < array[minIndex]) {
                minIndex = j;
            }
        }
        swap(&array[i], &array[minIndex]);
    }

    printf("find: %d\n", array[k - 1]);
}

void swap(int *value1, int *value2)
{
    int temp = *value1;
    *value1 = *value2;
    *value2 = temp;
}

posted on 2017-05-02 14:11  ljbguanli  阅读(888)  评论(0)    收藏  举报