random select algorithm(选择算法)

选择算法:在一个未排序的的序列中,选取第K小的元素。算法

 

static int random_select(int begin, int end, int k)
{
        assert(begin < end);
        assert(k >= 0);
        assert(k < end-begin);

        int rand = randint(begin, end);
        int left, right;

        partition(begin, end, rand, &left, &right);
        int idx = k+begin;
        if (idx < left)
                return random_select(begin, left, k);
        else if (idx >=left && idx<=right)
                return idx;
        else
                return random_select(right+1, end, idx-right-1);

}

static void partition(int begin, int end, int pivot_index, int *ret_left, int *ret_right)
{
#if 0
        printf("***********in partition*****************\n");
        print_array(begin, end);
        printf("pivot_index = %d\n", pivot_index);
#endif
        int pivot = A[pivot_index];
        swap(begin, pivot_index);

        int left = begin;
        int right = begin;
        int i;
        for (i=begin+1; i<end; i++)
        {
                if (A[i] > pivot)
                        ;
                else if (A[i] == pivot)
                {
                        swap(right+1, i);
                        right += 1;
                }
                else
                {
                        swap(left, i); left += 1;
                        swap(right+1, i); right += 1;
                }

        }
        *ret_left = left;
        *ret_right = right;
#if 0
        print_array(begin, end);
        printf("left = %d, right = %d \n", left, right);
        printf("***********end partition*****************\n");
#endif
}

用pseudo code写完,我会用了不到5分钟,而实际转换成代码调试,却花费了我半个多小时。如下是几点缘由。数组

1. 日常写pseudo code时,是和人的正常思惟一直,数组开始于1,最小的第k个元素就是最小的第k个元素。而实际写代码是,数组时从0开始的。这一点,很容易混淆。个人感受是,定义一套本身的符号和规则,使得pseudo code和程序代码的约定一致。好比,排名能够从0开始,第0小,第1小,..,第k小。好比,集合统一采起半开半闭的表示方法,全部有关数组的调用传入的参数(begin,end)都是半开半闭的.A[begin:end)dom

2. 用divide-and-conque方法解决问题时,边界条件很容易搞错。我认为,在写边界条件时,最好用简单示例看看对不对。不然,等程序跑起来,崩溃了,就悲剧了。ide

3. 函数的定义要明确,其表示的含义必定要明确。传入的参数的意义,返回的值的意义。我此次有一个bug就是由于random_select函数一开始定义返回的值的含义没有明确。函数

磨刀不误砍柴工,定义明确了再动手。spa

相关文章
相关标签/搜索