zoukankan      html  css  js  c++  java
  • 最坏情况为线性时间的选择算法

    最坏时间为线性时间的选择算法

    目标:返回数组中第k个元素的值,函数名称SELECT

    步骤:

    1. 将输入数组的n个元素划分成[n/5]组,每组5个元素,且最多只有一组由剩下的n mod 5个元素组成

    2. 寻找这[n/5]个元素的中位数,首先对这组元素进行插入排序,然后确定每组有序元素的中位数,即第三个元素

    3. 将这[n/5]个中位数,,放入一个新的数组,递归调用SELECT以找出中位数x,如果由偶数个中位数,约定x是较小的中位数

    4. 使用PARTITION,将x对输入数组进行划分,返回k,低区的k - 1个元素小于x,高区的n - k个元素大于x

    5. 比较k和i的大小,如果i < k,在低区递归调用SELECT,如果i > k,在高区递归调用SELECT,如果i = k,直接返回x。

    java实现:

    private static int select(int[] a,int l,int r,int k){
        if(r - l < 75){
            insertSort(a, l, r);    //用快速排序进行排序
            return a[l + k - 1];
        }
        int group = (r-l+5)/5;
        for(int i = 0;i<group;i++){
            int left = l+5*i;
            int right = (l + i * 5 + 4) > r ? r : l + i * 5 + 4;  //如果超出右边界就用右边界赋值
            int mid = (left+right)/2;
            insertSort(a, left, right);
            swap(a, l + i, mid);     // 将各组中位数与前i个 
        }
        int pivot = select(a,l,l+group-1,(group+1)/2);  //找出中位数的中位数
        int p = partition(a,l,r,pivot);    //用中位数的中位数作为基准的位置
        int leftNum = p - l;       //leftNum用来记录基准位置的前边的元素个数
        if (k == leftNum + 1)
            return a[p];
        else if (k <= leftNum)
            return select(a, l, p - 1, k);
        else                    //若k在基准位子的后边,则要从基准位置的后边数起,即第(k - leftNum - 1)个
            return select(a, p + 1, r, k - leftNum - 1);
    }
    
    private static int partition(int[] a,int l,int r,int pivot){   //适用于线性时间选择的partition方法
        int i = l;
        int j = r;
        while(true){
            while(a[i] <= pivot && i < r)
                ++i;   //i一直向后移动,直到出现a[i]>pivot
            while(a[j] > pivot)
                --j;   //j一直向前移动,直到出现a[j]<pivot
            if(i >= j) break;
            swap(a,i,j);
        }
        a[l] = a[j];
        a[j] = pivot;
        return j;
    }
    
    private static void insertSort(int[] a, int law, int high) {    //插入排序
           for (int i = law + 1; i <= high; i++) {  
               int key = a[i];  
               int j = i - 1;  
               while (j >= law && a[j] > key) {  
                   a[j + 1] = a[j];  
                   j--;  
               }  
               a[j + 1] = key;  
           }  
    }
    
    private static void swap(int[] a,int i,int j){
         int temp = a[i];
         a[i] = a[j];
         a[j] = temp;
     }

    c++实现

    #include <stdio.h>
    
    #define ARRAY_SIZE 10
    
    int select(int a[], int l, int r, int k);
    int partition(int a[],int p,int r,int pivot);
    void insertsort(int a[], int low, int high);
    void swap(int a[], int i, int j);
    
    int main(void)
    {
        int a[ARRAY_SIZE]={25,31,89,12,67,53,44,59,71,19};
        
        printf("%d
    ",select(a,0,ARRAY_SIZE-1,6));
    }
    
    int select(int a[], int l, int r, int k)
    {
        int group;
        int i;
        int left,right,mid;
        int pivot;
        int p,left_num;
        
        if (r-l+1 <= 5) {
            insertsort(a,l,r);
            return a[l+k-1];
        }
        
        group = (r-l+1+5)/5;
        for(i=0; i<group; i++) {
            left = l+5*i;
            right = (l+5*i+4) > r?r:l+5*i+4; //超出右便捷就使用右边界赋值
            mid = (left+right)/2;
            insertsort(a,left,right);
            //将各组中位数与前i个元素互换位置,方便递归select寻找中位数的中位数
            swap(a,l+i,mid); 
        }
        pivot = select(a,l,l+group-1,(group+1)/2); // 找出中位数的中位数
        
        // 用中位数的中位数作为基准的位置
        p = partition(a,l,r,pivot);
        left_num = p-l;
        if(k == left_num+1)
            return a[p];
        else if(k<=left_num) //k在低区
            return select(a, l, p-1, k);
        else //k在高区
            return select(a, p+1, r, k-left_num-1);
    }
    
    int partition(int a[],int p,int r,int pivot)
    {
        int x;
        int i=p-1;
        int j,tmp;
        
        for (j=p;j<r;j++) {
            if(a[j] == pivot) {
                swap(a,j,r);
            }
        }
        x = a[r];
        
        for(j=p;j<r;j++) {
            if(a[j]<=x) {
                i++;
                tmp=a[i];
                a[i]=a[j];
                a[j]=tmp;
            }
        }
        tmp=a[r];
        a[r]=a[i+1];
        a[i+1]=tmp;
        return i+1;
    }
    
    // 插入排序
    void insertsort(int a[], int low, int high)
    {
        int i,j;
        int key;
        
        for(i=low+1; i<=high; i++) {
            key = a[i];
            for (j=i-1;j>=low&&key<a[j];j--) {
                a[j+1] = a[j];
            }
            a[j+1] = key;
        }
    }
    
    void swap(int a[], int i, int j)
    {
        int tmp=a[i];
        
        a[i] = a[j];
        a[j] = tmp;
    }
  • 相关阅读:
    Postgresql HStore 插件试用小结
    postgres-xl 安装与部署 【异常处理】ERROR: could not open file (null)/STDIN_***_0 for write, No such file or directory
    GPDB 5.x PSQL Quick Reference
    postgresql 数据库schema 复制
    hive 打印日志
    gp与 pg 查询进程
    jquery table 发送两次请求 解惑
    python 字符串拼接效率打脸帖
    postgresql 日期类型处理实践
    IBM Rational Rose软件下载以及全破解方法
  • 原文地址:https://www.cnblogs.com/feng-ying/p/10705100.html
Copyright © 2011-2022 走看看