每日一篇-7.28-什么是数据结构中的堆

什么是堆

堆的物理结构相当于完全二叉树,并且完全二叉树是可以用数组存储的,堆顶元素是数组的第一项。

什么是堆排序

堆排序即将一个乱序的数组组成的二叉树经过调整成为有序数组。
插入一个元素需要将新元素追加到二叉树尾部,然后比较进行调整得到完全二叉树。时间复杂度为O(logN)。
删除堆顶元素,堆顶元素移出去之后将尾部的节点升为堆顶元素,然后进行比较下沉得到最新的堆。
那如何删除堆中指定元素呢?
看了一下知乎:在确定位置之后把堆末尾元素和它交换然后和删除堆顶元素一样不断做下移操作就好。但是需要维护一个hash表来索引每个元素在堆中的位置,保证复杂度O(log n)。

大顶堆和小顶堆

PriorityQueue pq = new PriorityQueue<>(list.length, (a, b) -> (a.val - b.val));
这个是自定义的对象之间的比较,两个对象之间比较大小使用.val数值,然后减号就是说,在维护堆的时候,要判断大小,判断的方法就是两个数相减,然后看大于0还是小于0
,然后减号就是说,在维护堆的时候,要判断大小,判断的方法就是两个数相减,然后看大于0还是小于0。此为构建小顶堆。

面试题:上万级数据取前K个大的数据

常见做法:构造K大的小顶堆,进行遍历比较,下边的代码是根据左程云老师的课写的

    public static class TopN{
        private int parent(int n){
            return (n - 1)/2;
        }
        private int left(int n){
            return 2*n + 1;
        }
        private int right(int n){
            return 2*n + 2;
        }

        //构建小顶堆
        private void buildHeap(int n, int[] data){
            for (int i = 1; i < n; i++){
                int t = i;
                while (t != 0 && data[parent(t)] > data[t]){
                    int temp = data[t];
                    data[t] = data[parent(t)];
                    data[parent(t)] = temp;
                    t = parent(t);
                }
            }
        }

        //调整data[i]
        private void adjust(int i, int n, int[] data){
            //why <=
            if (data[i] <= data[0]){
                return;
            }
            //置换堆顶
            int temp = data[i];
            data[i] = data[0];
            data[0] = temp;

            int t = 0;
            while (left(t) < n && data[t] > data[left(t)] || right(t) < n && data[t] > data[right(t)]){
                if (right(t) < n && data[right(t)] < data[left(t)]){
                    temp = data[t];
                    data[t] = data[right(t)];
                    data[right(t)] = temp;
                    t = right(t);
                }else {
                    temp = data[t];
                    data[t] = data[left(t)];
                    data[left(t)] = temp;
                    t = left(t);
                }
            }
        }

        public void findTopN(int n, int[] data){
            buildHeap(n, data);
            for (int i = 0; i < n; i++){
                adjust(i, n, data);
            }
        }

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值