• 从M个数中取TOP N


    从M个数中取TOP N

    将题目具体一点,例如,从100个数中取出从大到小排前10的数

    方法1:使用快速排序

           因为快速排序一趟下来,小于K的数都在K的前面,大于K的数都在K的后面

           如果,小于K的数有35个,大于K的数有64个

           那么,所以我们取top 10时,只需要在前35个数中进行递归快速排序,所以不需要对所有的数进行排序

    方法2:使用堆排序

           首先在前10个数中建议一个小根堆,

           因为是小根堆,所以前10个数中最小的数在index=0上

           然后遍历从11到100的数,如果p[i]>p[0],那么交换p[i]和p[0],然后重建堆

           遍历完成后,top 10的数就是堆中

    我用10万个随机数做实验,性能分析如下:



    表示当选取top 10时,快速排序花费3833微秒,堆排序花费642微秒

    结论:

      取top n时,当n小时,堆排序比快速排序有明显的优势,当n增加时,优势减少,甚至逆转

    以下是实验代码,仅供参考



    void adjust_min_heap(int*p, int index,int max)
    {
            int target,left=2*index+1,right=left+1;
            if(right <= max)
            {
                    //左右孩子都存在,找相对较小的
                    if( p[left]


                            target=left;
                    else
                            target=right;
            }
            else if(left==max)
            {
                    //只有左孩子存在
                    target=left;
            }
            else
            {
                    return;
            }
            if(p[target]


            {
                    exchange(&p[target],&p[index]);
                    adjust_min_heap(p,target,max);
            }
    }

    void find_top_n_min_heap(int*p, int num, int *n)
    {
            //如果总的个数还不够
            if(num<=*n)
            {
                    *n=num;
                    return;
            }

            int i;
            //将前n个数调整为小根堆
            for(i=*n/2-1;i>=0;i--)
                    adjust_min_heap(p,i,*n-1);

            int j;
            for(j=*n;j
                    if(p[j]>p[0])
                    {
                            exchange(&p[j],&p[0]);
                            adjust_min_heap(p,0,*n-1);
                    }
    }


    void find_top_n_1(int*p, int begin, int end, int n)
    {
            if(begin>=end)return;
            int i = begin+1,j=end;
            while(i
            {
                    while(i=p[begin])i++;
                    while(j>begin && p[j]<=p[begin])j--;
                    if(i
                    {
                            exchange(&p[i],&p[j]);
                    }
            }
            if(p[begin]


                    exchange(&p[begin],&p[j]);
            if(end-begin==1 && n==1)
            {
                    printf("%d ",p[begin]);
                    return;
            }
            if(j-begin+1 > n)
                    find_top_n_1(p,begin,j,n);
            else if(j-begin+1 == n)
            {
                    int k;
                    for(k=begin;k<=j;k++)
                            printf("%d ",p[k]);
            }
            else if(j-begin+1 < n)
            {

                    int k;
                    for(k=begin;k<=j;k++)
                            printf("%d ",p[k]);
                    find_top_n_1(p,j+1,end,n-j+begin-1);
            }
    }
    void find_top_n_quick_sort(int*p, int num, int n)
    {
            find_top_n_1(p,0,num-1,n);
    }

  • 相关阅读:
    aspnet_Membership_SetPassword
    FlipView使用
    结构之法字符串及链表的探索编程之美第3章
    window和linux下svn的使用
    【算法导论第13章】红黑树
    【算法导论】第16章贪心算法
    【算法导论】第15章动态规划
    ubuntu11.04下myeclipse开发环境的搭建(jdk6+tomcat6+myeclipse8.0+mysql)
    【matlab】在vc6.0中调用matlab中的正态分布产生随机数
    gnome/gtk+开发环境搭建
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4910783.html
Copyright © 2020-2023  润新知