• 假期学习第一步之......学习堆排序


    堆:分为小根堆和大根堆,就是说堆根的元素的关键字最小(最大);
    堆排序:Heapsort;
    时间复杂度:O(nlogn);
    优点:当题目描述只是说输出第K大或者是最大的数据的时候比快排有优势。快排的时间复杂度为O(nLogn),但是如果是堆排序的话时间复杂度为O(klogn),如果k<<n那么还是选择堆      排序;
    步骤:
    1>将待排序size个数据存储在数组内。如果下标2*i<size,那么2*i为i的左子树;如果2*i+1<size,那么2*i+1为i的右子树;
    2>建立初始堆。从最后一个非叶子节点开始调整,就是size/2。如果是想建小根堆的,建的初始堆堆根元素最大;如果是想建大根堆,初始堆堆根元素最小。
    3>堆排序。对于第i趟堆排序,调整堆根元素和第n-i+1结点交换,保证n-i+1~n-1是有序的。
    参考资料:http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html

    堆的应用:

    (一)哈夫曼树:POJ 3253

    (二)"和并项" POJ 2442 Sequence 

    连接:http://poj.org/problem?id=2442

    题目大意:给出m行数,每行n个数。从每行中选出一个数做和。那么有n^m个值,最后输出n个最小的和。 

    解题思路:
      如果从最暴力的方法思考,枚举每一行的每一个数和接下来的每一行的任意一个数求出最小的n个和,可定会超时的。
      但是其实有用的就是最小的n个数,那么依次枚举该行和前面所有行的情况中的最小的n个数的和的话,枚举的数据量会减少很多的。

      1>第一组数据存在data1[n]中,给他排序
      2>第二组数据存在data2[n]中,给他排序
      3>求出data2[0]与data1[]中数据的和,存在数组dataq[]中。给dataq[]从小到大排序。
      4>依次枚举data2[1]~data2[n]与data1[]作和。如果比 dataq[n-1]大,break; 否则dataq[n-1]=他们的和,重新排序dataq[];
      5>将dataq[]给data1[]
      6>重复2>-5>过程
      7>输出data1[]就是想要的结果

    扩展:STL中有一个heap.
      1>make_heap(heap, heap+n, cmp); 默认的情况下是将把“最大”的元素排列到首位,而其他元素看上去并非有序
      2>sort_heap(heap, heap+n, cmp); 进行堆排序
      3>pop_heap(heap, heap+n, cmp); 并不是将最大(最小元素弹出),而是将frist与last交换,在将frist与last-1做成一个堆
      4>push_heap(heap, heap+n, cmp); 将新元素加进去后做成一个堆;//感觉和1>没啥差别

    代码如下:

    View Code
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    #define N 2005
    int data1[N], data2[N], dataq[N];
    int main()
    {
        int i, j, tt, n, m, T;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d%d", &m, &n);
            memset(data1, 0, sizeof(data1));
            memset(data2, 0, sizeof(data2));
            memset(dataq, 0, sizeof(dataq)); 
            for(i=0; i<n; i++)
                scanf("%d", &data1[i]);
            sort(data1, data1+n);
            for(tt=0; tt<m-1; tt++)
            {
                for(i=0; i<n; i++)
                    scanf("%d", &data2[i]);
                int flag=0;
                sort(data2, data2+n);
                for(i=0; i<n; i++)
                    dataq[i]=data2[0]+data1[i];
                sort(dataq, dataq+n);
                for(i=1; i<n; i++)
                {
                    for(j=0; j<n; j++)
                    {
                        if(data2[i]+data1[j]>dataq[n-1])
                            break;
                        dataq[n-1]=data2[i]+data1[j];
                        sort(dataq, dataq+n);
                    }
                }
                for(i=0; i<n; i++)
                    data1[i]=dataq[i];
            }
            for(i=0; i<n-1; i++)
                printf("%d ", data1[i]);
            printf("%d\n", data1[n-1);
        }
        return 0;
    }
    View Code
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    #define N 2005
    int data1[N], data2[N], dataq[N];
    int main()
    {
        int i, j, tt, n, m, T;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d%d", &m, &n);
            memset(data1, 0, sizeof(data1));
            memset(data2, 0, sizeof(data2));
            memset(dataq, 0, sizeof(dataq)); 
            for(i=0; i<n; i++)
                scanf("%d", &data1[i]);
            
            for(tt=0; tt<m-1; tt++)
            {
                sort(data1, data1+n);
                for(i=0; i<n; i++)
                    scanf("%d", &data2[i]);
                sort(data2, data2+n);
                for(i=0; i<n; i++)
                    dataq[i]=data2[0]+data1[i];
                make_heap(dataq, dataq+n);
                for(i=1; i<n; i++)
                {
                    for(j=0; j<n; j++)
                    {
                        if(data2[i]+data1[j]>=dataq[0])
                            break;
                        dataq[0]=data2[i]+data1[j];
                        make_heap(dataq, dataq+n);
                    }
                }
                for(i=0; i<n; i++)
                    data1[i]=dataq[i];
            }
            sort(data1, data1+n);
            for(i=0; i<n-1; i++)
                printf("%d ", data1[i]);
            printf("%d\n", data1[n-1]);
        }
        return 0;
    }

    PS:此题最后不进行严格的控制格式也能ac such as:

    for(i=0; i<n; i++)
      printf("%d ", data1[i]);
    printf("\n");

    (三)优先队列: POJ 2051 Argus

    连接:http://poj.org/problem?id=2051

    题目大意:描述好难翻译。就是给出每个id 的num和id出现的间隔时间数pre。也就是说此id要间隔pre才能在出现。输出前k个id出现的次序,如果相同时间now内出现多个id,按照id 的num小的先输出。

    解题思路:堆的思想用优先队列实现,有两个优先级别按照now小的优先级别高,如果now的时间相同按照num小的先输出。

    扩展:优先队列重载符号,定义一个friend boo Name()函数进行设置优先级;

    代码如下:

    View Code
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<queue>
    using namespace std;
    struct ID
    {
        friend bool operator < (ID x, ID y)
        {
            if(x.now!=y.now)
                return y.now<x.now;
            else
                return y.num<x.num;
        }
        int num, per, now;
    };
    int main()
    {
        int k, t=0;
        char ch[50];
        ID id[1005];
        priority_queue<ID>Q;
        while(1)
        {
            scanf("%s", ch);
            if(strcmp(ch, "Register")==0)
            {
                scanf("%d%d", &id[t].num, &id[t].per);
                id[t].now=id[t].per;
                Q.push(id[t]);
                t++;
            }
            if(strcmp(ch, "#")==0)
                break;
        }
        scanf("%d", &k);
        while(k--)
        {
            ID temp;
            temp=Q.top();
            Q.pop();
            printf("%d\n", temp.num);
            temp.now+=temp.per;
            Q.push(temp);
        }
        return 0;
    }

    (四)...更新中....waiting....

  • 相关阅读:
    财务自由之路-我用Airtest刷抖音致富
    Python基础-背单词游戏
    别人是在谈薪酬,而你是在自残
    不写一行代码,使用Airtest完成自动化测试
    精致的JavaScript代码
    浅谈排序二叉树
    JavaScript 生产者消费者模型
    IDEA 激活码全家桶 webStorm亲测可用【更新日期2020.3.30】
    Cocos-JS HTTP网络请求
    初始OpenGL
  • 原文地址:https://www.cnblogs.com/Hilda/p/2848091.html
Copyright © 2020-2023  润新知