zl程序教程

您现在的位置是:首页 >  其他

当前栏目

堆、堆排序

2023-04-18 16:46:09 时间

堆的基本操作操作:

        1、插入一个数:

                数组末尾插入一个元素,并up()操作维护一下堆

                heap[ ++ size] = x; up(size);

        2、求集合当中的最小值:

                        小根堆的堆顶元素

                        heap[1]

        3、删除最小值:

                        使用最后一个节点的值覆盖第一个节点的值,再把数组的下标--,再使用头节点down(1)运算维护一下堆。

                        heap[1] = heap[size]; size --; down(1);

        4、删除任意一个元素(STL里面的堆无法进行的操作):

                        分情况判断,变大了或者变小了。

                        heap[k] = heap[size]; size -- ; down(k)或者up(k)

        5、修改任意一个元素(STL里面的堆无法进行的操作)

                        heap[k] = x; down(k);或者 up(k);

堆的基本结构:

        1、是一个平衡二叉树(即树除了最后一层节点可以不满以外,其它层的节点都是非空的,且最后一层节点是从左往右排列的)

        2、小根堆:根节点的值小于左右子节点的值,所以根节点是最小值

堆的存储:

        x的左二子是:2*x;x的右二子是:2*x+1;

        注:下标从1开始比较好

堆的基本操作(时间复杂度为O(nlogn)):

        down(x):x往下移动;当某个数变大的时候可以使用down操作        

                              令根节点和根节点、左、右子节点中的最小值进行交换,重复此操作

        up(x):x往上移动;当某个数变小的时候可以使用up操作

                        令数值较小节点和根节点、左、右子节点中的最小值进行交换,重复此操作   

例题及模板代码:

堆排序(down()函数的使用)

题目内容

输入一个长度为n的整数数列,从小到大输出前m小的数。 输入格式

第一行包含整数n和m。

第二行包含n个整数,表示整数数列。

输出格式

共一行,包含m个整数,表示整数数列中前m小的数。

数据范围

1≤m≤n≤10^5 , 1≤数列中元素≤10^9

输入样例:

5 3
4 5 1 3 2
输出样例:

1 2 3

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n,m;
int h[N],size;
void down(int u) {
    int t = u;//使用t记录根节点的值
    //让根节点分别和左右子节点进行对比
    if(u*2<=size&&h[u*2]<h[t])
        t=u*2;
    if(u*2+1<=size&&h[u*2+1]<h[t])
        t=u*2+1;
    if(u!=t) {//说明根节点不是最小的值,需要进行交换
        swap(h[u],h[t]);
        down(t);
    }
}
int main() {
    scanf("%d%d",&n, &m);
    for(int i=1; i<=n; i++)
        scanf("%d",&h[i]);
    size=n;
    for(int i=n/2; i; i--)//从n/2开始排序能将时间复杂度降到O(n)
        down(i);
    while(m--) {
        printf("%d ",h[1]);//取出最小值
        h[1]=h[size];//删除根节点
        size--;
        down(1);
    }
    return 0;
}