算法导论9.3-最坏情况线性时间的选择

#include <stdio.h>

#define exchange(a,b) if(a != b){ a = a ^ b; b = a ^ b; a = a ^ b; };

int insert_sort(int *A, int start, int length);
int partition(int *A, int start, int end);
int average(int *A, int start, int end, int p);
int find_middle(int *A, int start, int end, int p);
int select_x(int *A, int start, int end);
int select(int *A, int start, int end, int i);
int var_dump(int *A, int start, int end);

int main()
{
    int A[19] = {12,15,36,84,54,21,64,97,87,85,82,83,86,14,13,18,16,17,19};
    int i=10;//第i小的数
    int j;
    j = select(A, 0, sizeof(A)/sizeof(int)-1, i-1);
    printf("%dth:%d\n", i, j);
   
    return 0;
}

//插入排序
int insert_sort(int *A, int start, int length)
{
    int i,j;
    for(i = start; i < start+length; i++){
        for (j = i; j > start; j--){
            if(A[j] < A[j-1]){
                exchange(A[j], A[j-1]);
            }
        }
    }
    return 1;
}

//原地重排
int partition(int *A, int start, int end)
{
    int x = A[end];
    int i = start-1;
    int j;
    for(j = start; j < end; j++){
        if(A[j] < x){
            i++;
            exchange(A[i], A[j]);
        }
    }
    i++;
    exchange(A[i], A[end]);
    printf("partition:%d-%d-------------------------------------\n", start, end);
    var_dump(A, start, end);
    return i;
}

//将输入数组的n个元素划分为n/p组并排序
int average(int *A, int start, int end, int p)
{
    int i;
    //按p把数组划分为n/p个子数组
    for(i = start; i <= end; i+=p){
        if(i + p > end){
            insert_sort(A, i, end-i+1);
        }else{
            insert_sort(A, i, p);//对每个子数组进行插入排序
        }
    }
    printf("按p把数组划分为n/p个子数组-------------------------------------\n");
    var_dump(A, start, end);
}

//找出划分后每组的中位数
int find_middle(int *A, int start, int end, int p)
{
    int i;
    int j = start;
    //把中位数依次放到数组的前面
    for(i = start; i <= end; i+=p){
        if(i+p > end){
            exchange(A[j], A[(i+end+1)/2]);
        }else{
            exchange(A[j], A[(i+i+p)/2]);
        }
        j++;
    }
    printf("\n把中位数依次放到数组的前面-------------------------------------\n");
    var_dump(A, start, end);
    return j-1;
}

//找出n/p个中位数的中位数x
int select_x(int *A, int start, int end)
{
    //当范围内只有一个元素时返回
    if(start == end)
        return A[start];
    int p = 5;
    int j;
    average(A, start, end, p);
    j = find_middle(A, start, end, p);
    //对上面找到的中位数,调用select,找到他们的中位数x
    select_x(A, start, j);
}
//
int select(int *A, int start, int end, int i)
{
    int j,k;
    select_x(A, start, end);
    printf("找到x:%d-------------------------------------\n", A[start]);
    var_dump(A, start, end);
    //然后按x对数组进行划分,另k比小于x的元数数目多一,x即为第k小的数,n-k个数为比x大的数
    exchange(A[start], A[end]);
    k = partition(A, start, end);
    //如果i=k,则返回x。否则,如果i<k,则在低区递归调用select以找出第i小的元素,如果i>k,则在高区找第(i-k)个最小元素
    if(i == k)
        return A[k];
    if(i < k){
        select(A, start, k-1, i);
    }else{
        select(A, k+1, end, i);
    }
}

int var_dump(int *A, int start, int end)
{
    int i;
    for (i = start; i <= end; i++){
        printf("%4d", A[i]);
    }
    printf("\n");
}

//程序输出

// 按p把数组划分为n/p个子数组-------------------------------------
//   12  15  36  54  84  21  64  85  87  97  13  14  82  83  86  16  17  18  19

// 把中位数依次放到数组的前面-------------------------------------
//   36  85  82  18  84  21  64  15  87  97  13  14  12  83  86  16  17  54  19
// 按p把数组划分为n/p个子数组-------------------------------------
//   18  36  82  85

// 把中位数依次放到数组的前面-------------------------------------
//   82  36  18  85
// 找到x:82-------------------------------------
//   82  36  18  85  84  21  64  15  87  97  13  14  12  83  86  16  17  54  19
// partition:0-18-------------------------------------
//   19  36  18  21  64  15  13  14  12  16  17  54  82  83  86  97  84  85  87
// 按p把数组划分为n/p个子数组-------------------------------------
//   18  19  21  36  64  12  13  14  15  16  17  54

// 把中位数依次放到数组的前面-------------------------------------
//   21  14  54  36  64  12  13  19  15  16  17  18
// 按p把数组划分为n/p个子数组-------------------------------------
//   14  21  54

// 把中位数依次放到数组的前面-------------------------------------
//   21  14  54
// 找到x:21-------------------------------------
//   21  14  54  36  64  12  13  19  15  16  17  18
// partition:0-11-------------------------------------
//   18  14  12  13  19  15  16  17  21  36  64  54
// 按p把数组划分为n/p个子数组-------------------------------------
//   36  54  64

// 把中位数依次放到数组的前面-------------------------------------
//   54  36  64
// 找到x:54-------------------------------------
//   54  36  64
// partition:9-11-------------------------------------
//   36  54  64
// 找到x:36-------------------------------------
//   36
// partition:9-9-------------------------------------
//   36
// 10th:36

转载请注明:小Y » 算法导论9.3-最坏情况线性时间的选择

赞 (0) 评论 (0) 分享 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址