zoukankan      html  css  js  c++  java
  • 选择问题(selection problem)

    /*
        本文是选择问题:

              选择一组N个数当中的第k小的数(第k大的数类似)
         集中方法的实现代码

    */
     
     
     
    #include "sorting.h"
    #include "fatal.h"
     
    #define SORTING_BUBBLE  1
    #define SORTING_INSERTION   2
    #define SORTING_SELECTION   3
    #define SORTING_SHELL       4
    #define SORTING_QUICK       5
    #define SORTING_HEAP        6
    #define SORTING_MERGE       7
     
     
    /*
        解法1: 我们可以对这个乱序数组按照从小到大先行排序,然后

         取出前k大,总的时间复杂度为O(n*logn + k)。

    */
     
    int select_by_sorting(int A[], int N, int k, int SortingMethod)
    {
        if(k <1 || k > N )
        {
            fprintf (stderr, "error, k ?????? ");
            exit (EXIT_FAILURE);
        }
        switch(SortingMethod)
        {
        case SORTING_BUBBLE :
            bubble_sort (A, N,IntComp);
             return A[ k-1];
        case SORTING_INSERTION :
            insertion_sort (A, N,IntComp);
             return A[ k-1];
        case SORTING_SELECTION :
            selection_sort (A, N,IntComp);
             return A[ k-1];
        case SORTING_SHELL :
            shell_sort (A, N,IntComp);
             return A[ k-1];
        case SORTING_QUICK :
            quick_sort (A, N,IntComp);
             return A[ k-1];
        case SORTING_HEAP :
            heap_sort (A, N,IntComp);
             return A[ k-1];
        case SORTING_MERGE :
            merge_sort (A, N,IntComp);
             return A[ k-1];
        default:
            Error ("not a known sorting method!");
        }
        return 0;
    }
    /*
        解法2: 先把前k个元素读进数组并排序(递增顺序),接着,将剩下

         的元素逐个读入。当新元素大于数组中的第k个元素是则忽略,否则将
         其放入正确的位置,旧的第k个元素将被挤掉!

    */
    int select2(int A[], int N, int k)
    {
        // 可改进为前面k个数原地排序。
        int *Ak = malloc(sizeof(int )*k);
        Ak[0 ] = A[0];
        int i,j ;
        for(i = 1; i < k; i++)
        {
             for(j = i- 1; j >= 0 ; j--)
             {
                 if(A [i]< Ak[j])
                    Ak [j+ 1] = Ak[ j];
                 else
                     break;
             }
            Ak [j+ 1] = A[ i];
        }
        for(i = k ; i < N; ++i )
        {
             if(Ak [k- 1]<= A [i]) continue;
            
             for(j = k- 2; j >=0; --j)
             {
                 if(A [i] < Ak[j ])
                    Ak [j+ 1] = Ak[ j];
                 else
                     break;
             }
            Ak [j+ 1] = A[ i];
        }
        int ret = Ak [k- 1];
        free(Ak );   
        return ret ;
    }
     
    /*
        解法3:利用选择排序或交互排序,K次选择后

         即可得到第k大的数。总的时间复杂度为O(n*k)

    */
     
    int select3(int A[], int N, int k)
    {
        int minIndex ;
        int tmp;
        int i,j ;
        for(i = 0; i <k; ++i)
        {
            minIndex = i;
             for(j = i+ 1; j <N; ++j)
                 if(A [minIndex] > A [j])
                    minIndex = j;
            tmp = A[ minIndex];
            A [minIndex] = A [i];
            A [i] = tmp;
        }
        return A [k- 1];
    }
     
    /*
        解法4:利用快速排序的思想,从数组S中随机找出一个元素X,

         把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素
         小于X。这时有两种情况:
              1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
              2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n)

     
    */
    int partition(int A[], int p, int q)
    {
        // select a pivot
        // for simplicity select p as pivot
        int i,j ;
        i = p ;
        int tmp;
        for(j = p +1; j <= q ; j++)    
        {
             if(A [j] < A[p ])
             {
                 ++i;
                 if(i == j)
                     continue;
                tmp = A[ i];
                A [i] = A[j ];
                A [j] = tmp;
             }
        }
        tmp = A [i];
        A[i ] = A[p];
        A[p ] = tmp;
        return i ;
    }
    int findk( int A[], int p, int q, int k)
    {
        int r = partition (A, p,q);
        if(k-1 == r)
             return A[ r];
        else if(r > k - 1)
        {
             return findk( A,p,r -1, k);
        }else
             return findk( A,r+1 ,q, k);
    }
    int select4(int A[], int N, int k)
    {
        return findk (A, 0,N -1, k);
    }
     
     
    #define ITEMNUM 5000
    #define METHODNUM 10
    int main()
    {
        int A[METHODNUM ][ITEMNUM];
        int k = 564;
        int temp;
        for(int i = 0 ; i < ITEMNUM; ++i)
        {
            temp = rand();
             for(int j = 0; j < METHODNUM; j++)
                A [j][ i] = temp ;
        }
        
        int r1,r2 ,r3, r4,r5,r6 ,r7, r8;
        r1 = select_by_sorting (A[ 0],ITEMNUM ,k, SORTING_BUBBLE);
        r2 = select_by_sorting (A[ 1],ITEMNUM ,k, SORTING_INSERTION);
        r3 = select_by_sorting (A[ 2],ITEMNUM ,k, SORTING_SELECTION);
        r4 = select_by_sorting (A[ 3],ITEMNUM ,k, 4);
        r5 = select_by_sorting (A[ 4],ITEMNUM ,k, 5);
        r6 = select_by_sorting (A[ 5],ITEMNUM ,k, 6);
        r7= select_by_sorting (A[ 6],ITEMNUM ,k, 7);
        r8 = select2 (A[ 7],ITEMNUM ,k);
        int r9 = select3 (A[ 8],ITEMNUM ,k);
        printf("%d %d %d %d %d %d %d %d " ,r1, r2,r3,r4 ,r5, r6,r7,r8 );
        printf("%d " ,r9);
        int r10 = select4 (A[ 9],ITEMNUM ,k);
        printf("%d " ,r10);
        return 0;
    }
  • 相关阅读:
    用Python完成一个汇率转换器
    鸿蒙如何用JS开发智能手表App
    鸿蒙如何用JS开发智能手表App
    SAP Spartacus SplitViewComponent Migration 的一个具体例子
    SAP Spartacus B2B 页面 Popover Component 的条件显示逻辑
    SAP Spartacus 升级时关于 schematics 的更新
    SAP Spartacus B2B 页面 Disable 按钮的显示原理
    SAP Spartacus B2B 页面 Disable Confirmation 对话框的显示原理
    通过 Feature Level 动态控制 SAP Spartacus 的页面显示
    SAP Commerce Cloud Build Manifest Components
  • 原文地址:https://www.cnblogs.com/jimmysue/p/3815214.html
Copyright © 2011-2022 走看看