利用堆解决top k问题

解决思路

     1、构建小顶堆,则堆顶元素就是目前k个元素中最小的元素

     2、后续元素依次和堆顶元素比较,如果小于堆顶元素,则next

     3、如果大于堆顶元素,将此元素插入堆中,重新堆化

源码

package dataStructures.tree.heap;

/**
 * 利用堆解决top k问题
 * 堆是一种完全二叉树,堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点
 * 堆有很多应用,例如可以用来排序,求top k问题,流里面的中值 ,流里面的中位数等
 */
public class Topk {
    public static void main(String[] args) {
        int[] data_test = {0,2,4,6,8,6,4,23,55,1};
        Topk.Heap heap = new Topk().new Heap(4);
        for (int i = 1; i < data_test.length; i++) {
            heap.insert(data_test[i]);
        }
        heap.printAll(heap.data, heap.count);
    }
    
    /**
     * 
     * @author victory
     * @date 2019年2月19日 上午10:56:19
     * @Description 堆的实现
     */
    public class Heap {
        private int[] data;//存放数据
        private int capacity;//堆容量
        private int count;//堆中实际存放数据的个数

        public Heap(int capacity) {
            this.capacity = capacity;
            this.data = new int[capacity+1];
            this.count = 0;
        }
        
        /**
         * 向堆中插入数据
         * @param value
         */
        public void insert(int value) {
            if (count < capacity) {
                count++;
                data[count] = value;
                int i = count;
                while (i/2 > 0 && data[i/2] > data[i]) {
                    swap(data, i, i/2);
                    //此处用位运算代替除2操作,效率更高
                    i >>= 1;
                }
            } else {
                if (value <= data[1]) return;
                data[1] = value;
                printAll(data, count);
                heapify();
                printAll(data, count);
            }
        }

        //插入元素后需要重新调整堆
        private void heapify() {
            int i = 1;
            while (true) {
                int minPos = i;
                if (i * 2 <= count && data[i*2] < data[i]) minPos = i*2;
                if (i * 2 + 1 <= count && data[i*2+1] < data[minPos]) minPos = i*2+1;
                if (minPos == i) break;
                swap(data, i, minPos);
                i = minPos;
            }
        }
        
        private void swap(int[] data, int index1, int index2) {
            int tmp = data[index1];
            data[index1] = data[index2];
            data[index2] = tmp;
        }
        
        //打印堆中的所有数据
        public void printAll(int[] data, int count) {
            for (int i = 1; i <= count; i++) {
                System.out.print(data[i] + ",");
            }
            System.out.println();
        }
    }
}

github地址

     https://github.com/zuolovezhai/Data-Structures-Algorithms/commit/5b625500886eff764b78affd385a0790ad389dfb

你可能感兴趣的:(数据结构)