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

相關文章
相關標籤/搜索