算法——TOP K问题最小堆实现扩展

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CYXLZZS/article/details/51393052

1. 概述

上文我们讲到TOP K问题最小堆的实现,采用的比较基本数据类型int。这里我们将扩展到比较对象

2. 代码实现

这里我们直接上代码,这里的扩展最小堆我们取名为ExMinHeap,实现如下

package org.cyxl.common;

/**
 * 扩展最小堆,采用泛型,存储的对象必须实现Comparable接口
 *
 * Created by jeff on 16/5/11.
 */
public class ExMinHeap<T extends Comparable>
{
    // 堆的存储结构 - 数组(这里为Object数组,数组中的具体类型为T)
    private Object[] data;

    /**
     * 初始化堆的大小
     * @param k
     */
    public ExMinHeap(int k)
    {
        this.data = new Object[k];
    }

    /**
     * 调整堆为最小堆, 比较时很重要的一点null为最小
     *
     * @param i
     */
    private void adjustHeap(int i)
    {
        // 获取左右结点的数组下标
        int l = left(i);
        int r = right(i);

        // 这是一个临时变量,表示 跟结点、左结点、右结点中最小的值的结点的下标
        int smallest = i;

        // 存在左结点,且左结点的值小于根结点的值
        T parent = (T)data[i];
        if (l < data.length){
            T left = (T)data[l];
            if(parent.compareTo(left)>0){
                smallest = l;
            }
        }

        T min = (T)data[smallest];
        // 存在右结点,且右结点的值小于以上比较的较小值
        if (min!=null && r < data.length){
            T right = (T)data[r];
            if(min.compareTo(right)>0){
                smallest = r;
            }
        }


        // 左右结点的值都大于根节点,直接return,不做任何操作
        if (i == smallest)
            return;

        // 交换根节点和左右结点中最小的那个值,把根节点的值替换下去
        swap(i, smallest);

        // 由于替换后左右子树会被影响,所以要对受影响的子树再进行adjustHeap
        adjustHeap(smallest);
    }

    /**
     * 获取右结点的数组下标
     * @param i
     * @return
     */
    private int right(int i)
    {
        return (i + 1) << 1;
    }

    /**
     * 获取左结点的数组下标
     *
     * @param i
     * @return
     */
    private int left(int i)
    {
        return ((i + 1) << 1) - 1;
    }

    /**
     * 交换元素位置
     *
     * @param i
     * @param j
     */
    private void swap(int i, int j)
    {
        T tmp = (T)data[i];
        data[i] = data[j];
        data[j] = tmp;
    }

    /**
     * 替换根元素,并重新adjustHeap(注意开始根节点为null的情况)
     *
     * @param element
     */
    public void add(T element)
    {
        if(element.compareTo(data[0])>0) {
            //具体存储的对象类型为T
            data[0] = element;
            adjustHeap(0);
        }
    }

    public String toString(){
        StringBuilder builder = new StringBuilder();
        builder.append("{");
        for (int i=0;i<data.length;i++){
            T t = (T)data[i];
            if(t!=null) {
                builder.append(t.toString());
                if (i != data.length - 1) {
                    builder.append(",");
                }
            }
        }
        builder.append("}");

        return builder.toString();
    }
}

代码中有比较详细的注释,可以对照先前的那篇博客进行对比理解。这里我们对存入堆的对象进行泛型的控制,它必须实现Comparable接口。

3. 验证测试

首先我们先创建一个符合扩展最小堆的对象HeapData

package org.cyxl.common;

/**
 * Created by jeff on 16/5/12.
 */
public class HeapData implements Comparable {
    private int value;


    public HeapData(int value){
        this.value = value;
    }

    public int getValue(){
        return value;
    }

    @Override
    public int compareTo(Object o) {
        if(o==null){
            //这点对于比较很重要
            return 1;
        }
        HeapData that = (HeapData)o;

        if(that.getValue()==this.getValue()){
            return 0;
        }else if(that.getValue()>this.getValue()){
            return -1;
        }else {
            return 1;
        }

    }

    public String toString(){
        return value+"";
    }
}

由于HeapData实现了Comparable接口(必须重写compareTo方法),所以它符合扩展最小堆数据的要求

接下来我们写个main函数来测试一下

public static void main(String[] args){
        int k = 10;
        ExMinHeap<HeapData> exMinHeap = new ExMinHeap<HeapData>(k);
        int n = 10;
        for(int i=0;i<n;i++){
            int value = new Random().nextInt(100);
            System.out.print(value+" ");
            HeapData data = new HeapData(value);

            exMinHeap.add(data);
        }
        System.out.println();

        System.out.println(exMinHeap);
    }

结果为

25 58 62 99 70 11 60 62 61 78 
{62,62,99,78,70}

(随机的生成的10个数字,可能数字本身和我这里有区别)

猜你喜欢

转载自blog.csdn.net/CYXLZZS/article/details/51393052
今日推荐