首页 > 代码库 > Java 小根堆排序

Java 小根堆排序

Counter类:计数器 IntPk中包含主键

public class Counter extends IntPK{

    private int count;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

MinHeap类:最小堆排序类

package com.ryx.incantation.model;

import com.ryx.incantation.entity.Counter;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by ZHB on 2014/12/27.
 */
public class MinHeap {
    private static Logger logger = Logger.getLogger(MinHeap.class);

    public MinHeap() {

    }

    // 交换元素位置
    private void swap(List<Counter> data, int i, int j) {
        Counter tmp = data.get(i);
        data.set(i, data.get(j));
        data.set(j, tmp);
    }

    public List<Counter> headSort(List<Counter> sortArray) {
        for (int i = 0; i < sortArray.size() - 1; i++) {
            buildMaxHeap(sortArray, sortArray.size() - 1 - i);
            swap(sortArray, 0, sortArray.size() - 1 - i);
        }
        return sortArray;
    }

    //建立小根堆
    public void buildMaxHeap(List<Counter> data, int lastIndex) {
        //从lastIndex节点的父节点开始舰堆
        for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
            //保存正在判断的节点
            int k = i;
            //这里为每个节点建立大顶堆,只要这个根节点还有子节点
            while ((2 * k + 1) <= lastIndex) {
                //假设左节点的值时最大的
                int biggerIndex = 2 * k + 1;
                //说明还有右节点是存在的
                if (biggerIndex < lastIndex) {
                    //选出子节点中最大的值
                    if (data.get(biggerIndex).getCount() < data.get(biggerIndex + 1).getCount()) {
                        biggerIndex++;
                    }
                }
                //将跟节点与子节点进行比较
                if (data.get(k).getCount() < data.get(biggerIndex).getCount()) {
                    swap(data, k, biggerIndex);
                    k = biggerIndex;
                } else {
                    break;
                }
            }
        }
    }

    // 获取对中的最小的元素,根元素
    public Counter getRoot(List<Counter> result) {
        return result.get(0);
    }

    // 从data数组中获取最大的k个数
    public List<Counter> getTopK(List<Counter> data, int k) {
        // 先取K个元素放入一个数组topk中
        List<Counter> topk = new ArrayList<>();
        for (int i = 0; i < k; i++) {
            if (i == data.size()) {
                break;
            }
            topk.add(data.get(i));
        }

        List<Counter> result = headSort(topk);

        // 从k开始,遍历data
        for (int i = k; i < data.size(); i++) {
            Counter root = getRoot(result);
            // 当数据大于堆中最小的数(根节点)时,替换堆中的根节点,再转换成堆
            if (data.get(i).getCount() > root.getCount()) {
                result.set(0, data.get(i));
                headSort(result);
            }
        }
        Collections.reverse(result);
        return result;
    }
}

主程序调用:

List<Counter> TopK =  new MinHeap().getTopK(allCounterList, page * count);


本文出自 “CEO之路” 博客,请务必保留此出处http://zhaohaibo.blog.51cto.com/7808533/1596629

Java 小根堆排序