小根堆、大根堆

小根堆

小根堆是指堆顶的值最小的树,小根堆的每个子节点的值都比父节点的值大,也因为这样,一般用来在n个数中找m个最大的数

/**
 * 小根堆:
 * 适合在n个数中寻最大的m个数
 * @author lzq
 *
 */
public class XiaoDinDui {
    /**
     * 默认初始化长度
     */
    private static int LENGTH = 10;
    /**
     * 当前堆的长度
     */
    private static int size;
    /**
     * 堆的最大长度
     */
    private static int maxsize;
    /**
     * 数据
     */
    public static int[] queue;

    public XiaoDinDui() {
        initialize(LENGTH);
    }


    public XiaoDinDui(int maxsize) {
        if(maxsize < 1) {
            System.out.println("非法长度");
        }
        initialize(maxsize);
    }


    /**
     * 初始化堆
     * @param lENGTH2
     */
    private void initialize(int capacity) {
        this.maxsize = capacity;
        queue = new int[capacity];
        size = 0;
        }
    /**
     * 判断堆是否满了
     * @return
     */
    public static boolean isFull() {
        if(size >= maxsize) {
            return true;
        }
        return false;
    }
    /**
     * 获得堆顶元素
     * @return queue[0]
     */
    public static int getTop() {
        return queue[0];
    }
    /**
     * 删除堆顶元素
     * @return
     */
    public static int remove() {
        //获取堆顶元素
        int cur = getTop();
        //获取最后一个元素
        int tmp = queue[--size];
        //将最后一个元素放到第一个
        queue[0] = tmp;
        //进行调整
        adjustment2(0,tmp);
        //返回堆顶元素
        return cur;
    }
    /**
     * 从下往上调整
     * @param k       需要调整的位置
     * @param value   需要调整的值
     */
    public static void adjustment1(int k,int value) {
        //直到调整到堆顶元素k=0号下标
        while(k > 0) {
            //获取父节点
            int root = (k-1)/2;
            //如果父节点的值小于要调整的值,说明符合小顶堆要求,跳出去
            if(queue[root] <= value) {
                break;
            }
            //如果父节点的值大于要调整的值,则需要将父节点继续往下移
            queue[k] = queue[root];
            //k往上移动
            k = root;
        }
        //将要调整的值放到k位置
        queue[k] = value;
    }
    /**
     * 从上往下调整
     * @param k       需要调整的位置
     * @param value   需要调整的值
     */
    public static void adjustment2(int k,int value) {
        //调整的界限
        int half = size/2;
        while(k < half) {
            //获取左孩子下标
            int left = k*2+1;
            //获取左孩子的值
            int leftvalue = queue[left];
            //获取右孩子下标
            int right = left+1;
            //先判断是否存在左右孩子,找到最小的放到leftvalue
            if(right < size && leftvalue > queue[right]){
                    leftvalue = queue[right];

            }
            //如果孩子节点大于要调整的值,说明找到了位置,跳出
            if(leftvalue > value) {
                break;
            }
            //如果没有找到,将小的孩子放到根节点
            queue[k] = queue[left];
            //k往下移
            k = left;
        }
        //将值放到k号位置
        queue[k] = value;
    }
    /**
     * 添加元素
     * @param x
     */
    public static void add(int x) {
        if(size == 0) {
            //如果堆中没有数据,放第一个
            queue[size++] = x;   
        }else if(!isFull()) {
            adjustment1(size++,x);
        }else {
            //如果堆顶元素比x还小,则移除堆顶元素,把x换进去
            if(x > getTop()) {
                remove();
                add(x);
            }
        }
    }
    /**
     * 打印堆
     */
    public static void show() {
        for(int i = 0;i < size;i++) {
            System.out.print(queue[i]+" ");
        }
        System.out.println();
    }

   public static void look_for(int[] array) {
       for(int i = 0;i < array.length;i++) {
           add(array[i]);
       }
   }
}
public class A {

    public static void main(String[] args) {
        XiaoDinDui x = new XiaoDinDui(5);
        int[] array = {25,36,45,98,12,16,96,5,4,28,37,45,36,45};
        x.look_for(array);
        x.show();
        }
}

运行结果:

45 45 45 98 96 

大根堆

大根堆与小根堆类似,只是它的堆顶元素值是最大的,子节点的值小于父节点的值,一般用来在n个数中找出最小的m个数

/**
 * @author lzq
 *
 */
public class DaGenDui {
    private static final  int  LENGTH = 10;
    private int size;
    private int maxsize;
    private int[] array;

    public DaGenDui() {
        initHeap(LENGTH);
    }
    public DaGenDui(int capacity) {
        if(capacity<1) {
            System.out.println("非法长度");
        }
        initHeap(capacity);
    }


    private void initHeap(int initCapacity) {
        this.maxsize = initCapacity;
        array = new int[initCapacity];
        size = 0;
    }


    public void add(int x) {
        if(size==0) {
            array[size++] = x;
        }else if(!isFull()) {
            adjust1(size++,x);
        }else {
            if(x < getTop()) {
                remove();
                add(x);
            }
        }
    }

    public boolean isFull() {
        return size>=maxsize;
    }

    public int getTop() {
        return array[0];
    }

    public int remove() {
        int cur = getTop();
        int temp = array[--size];
        array[0] = temp;
        adjust2(0,temp);
        return cur;
    }

    private void adjust1(int k,int value) {
        while(k>0) {
            int root = (k-1)>>>1;
            if(array[root]>=value) {
                break;
            }
            array[k] = array[root];
            k = root;
        }
        array[k] = value;
    }

    private void adjust2(int k,int vale) {
        int half = size>>>1;
        while (k<half) {
            int child = (k<<1)+1;
            int childVal = array[child];
            int RightChild = child+1;
            //此处要找最大的孩子
            if(RightChild<size && childVal<array[RightChild]) {
                childVal = array[child = RightChild];
            }
            if(childVal<vale) {
                break;
            }
            array[k] = array[child];
            k = child;
        }
        array[k] = vale;
    }

    public void show() {
        for (int i = 0; i < size; i++) {
            System.out.print(array[i]+" ");
        }
        System.out.println();
    }

    public void put(int[] a) {
        for (int i = 0; i < a.length; i++) {
            add(a[i]);
        }
    }
}

运行结果:

25 12 16 5 4 

猜你喜欢

转载自blog.csdn.net/QQ2899349953/article/details/81260250