zoukankan      html  css  js  c++  java
  • 【算法学习笔记】21.算法设计初步 求第k个数 划分法 快排法

    第一种方法, 主要是分组每组五个排序,取中位数,再取中位数的中位数然后进行分割,根据MoM和k的比较进行递归查找。

    但是貌似当数量一大的时候,容易出现问题。暂时留有一定的疑问。这个的复杂度也是O(n)。

    //选择排序
    void SelectSort(long* A,int len=5){
        for (int i=0; i<len; i++) {
            for (int j=i+1; j<len; j++) {
                if(A[i]>A[j]){
                    long t=A[i];
                    A[i]=A[j];
                    A[j]=t;
                }
            }
        }
    }
    //划分A 长度是len 把A分成比x大的和和比x小的两部分
    int Partition(long *A,int len,long x){
        //初始化三个数组
        //left是比x小的 right是比x大的 middle是和x一样的
        long left[Max_N],right[Max_N],middle[Max_N];
        int left_len=0,right_len=0,middle_len=0;
        //循环的去看A中各个元素 然后放在不同的数组里
        for (int k=1; k<=len; k++) {
            if(A[k-1]<x)
                left[left_len++]=A[k-1];
            else if(A[k-1]>x)
                right[right_len++]=A[k-1];
            else
                middle[middle_len++]=A[k-1];
        }
        //cur是光标 把三个数组按顺序放回A中
        int cur=0;
        for (; cur<left_len; cur++)
            A[cur]=left[cur];
        A[cur] = x;
        for (int j=0; j<middle_len; j++)
            A[cur+j]=middle[j];
        for (int j=0; j<right_len; j++)
            A[cur+j]=right[j];
        //返回第一个x的下标
        return left_len+1;
    }
    
    long Select(long* A,int len,int i){
    
        if (len<=5) {    //每组分成5个 如果小于5 直接返回
            SelectSort(A,len);
            return A[i-1];
        }
        
        for (int j=1; j<=len/5; j++) {
            SelectSort(A+(j-1)*5,5);//每小组进行排序
            //交换 A[j-1]和A[(j-1)*5+3] 要把所有的中位数前移!为了取中位数的中位数MoM
            //不用考虑剩余的没有进行分组中的元素 因为他们都在划分中考虑了
            long t=A[(j-1)*5+2];//t是5个数中的中位数
            A[(j-1)*5+2]=A[j-1];
            A[j-1]=t;
        }
        //取MoM 中位数的中位数
        long MoM = Select(A, len/5, (len/10==0)?1:len/10);
        //k是划分成两半之后MoM所在的位置
        int k = Partition(A, len, MoM);
        
        long t=0;
        if (k==i)
            //如果k正好是要找的那个元素 就直接返回MoM
            t = MoM;
        //在两半中继续找
        else if(k>i)
            t = Select(A, k-1, i);
        else
            t = Select(A+k-1, len-k, i-k);
        return t;
    }
    View Code


    第二种方法 利用快速排序

    先简单说一下快速排序的思想。

    从核心思想上来说,快速排序和归并排序很像,只是归并排序的两边并不是有序的,所以最后要进行合并,而快速排序则不是。

    1.划分问题:把数组的各个元素重排后分成两部分,使左边的每个元素都小于右边的元素

    2.递归求解:左右分别排序

    3.合并问题:不用合并,因为此时数组已经拍完序。

    划分的过程有多种多样。

    第k个数正好就是可以判断k 分别每次都进行选择在左边或者右边进行查找。

    快速排序(Quicksort)是对冒泡排序的一种改进。

    最简单易懂的版本。

    void QckSort(int* A,int low,int high){
        //low是所需排的最低下标 hight是所需排的最高下标
        if(high<=low) return;
        int i=low,j=high;
        int key = A[i];//随便找个key 方便起见取第一个 留出回旋的空间
        while (i<j) {//两个机器人还没有相遇的时候
            //右边的j机器人向左走 遇到比key小的就扔给i机器人
            while (i<j && A[j]>=key) j--;
            //开始扔
            A[i] = A[j];
            //左边的i机器人向右走 遇到比key大的石头就扔给j机器人
            while (i<j && A[i]<=key) i++;
            //开始扔
            A[j] = A[i];
        }
        A[i]=key;//此时两个机器人已经相遇了,所以是i==j
        //因为此时i是key 不用考虑
        QckSort(A, low, i-1);//注意是[low,i-1]
        QckSort(A, i+1, high);//是[i+1,high]
        return;
    }


    于是找第k个数就变成了这样

    //找第k个数
    int QckFind(int* A,int low,int high,int k){
        //low是所需排的最低下标 hight是所需排的最高下标
        if(high<=low) return A[low];
        int i=low,j=high;
        int key = A[i];//随便找个key 方便起见取第一个 留出回旋的空间
        while (i<j) {//两个机器人还没有相遇的时候
            //右边的j机器人向左走 遇到比key小的就扔给i机器人
            while (i<j && A[j]>=key) j--;
            //开始扔
            A[i] = A[j];
            //左边的i机器人向右走 遇到比key大的石头就扔给j机器人
            while (i<j && A[i]<=key) i++;
            //开始扔
            A[j] = A[i];
        }
        A[i]=key;//此时两个机器人已经相遇了,所以是i==j
        //因为此时i是key 不用考虑
        if(i==(k-1))
            return key;
        if(i<(k-1))
            return QckFind(A,low,i-1,k);
        else
            return QckFind(A,i+1,high,k-1-i);
    }



  • 相关阅读:
    实例协议分析RFC1483:AAL5和几种常见ADSL接入技术
    2.2.3 Runaround Numbers
    2.2.2 Subset Sums
    2.2.1 Preface Numbering
    Dynamic Programming
    Data Structures
    2.1.5 Hamming Codes
    2.1.4 Healthy Holsteins
    2.1.3 Sorting a Three-Valued Sequence
    2.1.2 Ordered Fractions
  • 原文地址:https://www.cnblogs.com/yuchenlin/p/4379250.html
Copyright © 2011-2022 走看看