定义:
二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。二叉堆有两种:最大堆和最小堆。最大堆:父结点的键值总是大于或等于任何一个子节点的键值;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。
使用范围:
读写算法复杂度都是O(logn),是一种相对平衡的数据结构,用于优先级队列,保证头结点最优,之后节点无序,每次获取之后执行树深度重排.
直接上代码–二叉堆实现
package com.zby.calc;
import java.util.Random;
/**
*
* 最大堆:比较算法,最大的在上面
* 最小堆:最小的在上面
* 算法复杂度O(log n)
*
* @author zby
* @time 2021/6/8 14:36
* ****************************************
*/
public class A_BinaryHeap<V extends Comparable<V>> {
private V[] root;
// 当前容量
private int size;
public A_BinaryHeap(V[] root) {
this.root = root;
}
/**
*
* @desc 拿出队列头
******************************************
*/
public V removeTop() {
V backdata = root[1];
if(backdata==null)
return null;
root[1] = root[size];
root[size] = null;
size--;
sink(1);
return backdata;
}
/**
*
* @desc 插入
******************************************
*/
public void add(V v) {
size++;
root[size] = v;
swim(size);
}
/**
*
* @desc 交换对象
******************************************
*/
public void exchangeV(int index1,int index2) {
V v = root[index1];
root[index1] = root[index2];
root[index2] = v;
}
/**
*
* @desc 下沉
******************************************
*/
public void sink(int index) {
if(2*index>size)
return;
int changeIndex = 2*index;
if(size>=2*index+1&&root[2*index].compareTo(root[2*index+1])<0)
changeIndex = 2*index+1;
if(root[index].compareTo(root[changeIndex])>=0)
return;
exchangeV(index,changeIndex);
sink(changeIndex);
}
/**
*
* @desc 上浮
******************************************
*/
public void swim(int index) {
if(index<=1)
return;
if(root[index/2].compareTo(root[index])<0) {
exchangeV(index / 2, index);
swim(index / 2);
} else
return;
}
/**
*
* @desc main
******************************************
*/
public static void main(String[] args) {
A_BinaryHeap<Student> ss = new A_BinaryHeap<>(new Student[1000]);
for (int i = 0; i < 10; i++) {
ss.add(new Student(new Random().nextInt(1000)));
// System.out.println("--------------------------------------------");
// for (int i1 = 0; i1 < ss.root.length; i1++) {
// Student s = ss.root[i1];
// if(s==null)
// continue;
// System.out.println(i1+"--------"+s.getIq());
// }
}
System.out.println("拿出数据:");
for (int j=0;j<100;j++) {
Student student = ss.removeTop();
if(student==null)
continue;
System.out.println(student.getIq());
}
}
static class Student implements Comparable<Student> {
int iq;
public Student(int iq) {
this.iq = iq;
}
public int getIq() {
return iq;
}
public int compareTo(Student o) {
return this.getIq()-o.getIq();
}
}
}
- 当新增一个节点,放在最后,以此往上遍历,上浮到最高的位置.相当于二分查找,数据越多,速度相对更快.
- 获取头结点之后,将size位置的根节点填充到头节点 然后开始下沉计算.
- 好处在于整颗数放在一个数组里面,父节点当前节点index/2,左子节点2index,右子节点==2index+1,整颗数能快速计算得到结果.
- 这种结构适用于插入结果位置随机,不像英雄评分排行榜这种,穿了一件装备加分,但是不足以撼动整棵树,浮动极小,一般上浮或下沉1,2个单位,还有很大概率不会变动,当然也不能得到一个顺序的数据结构.
- 总之,只想得到期待值最高的值,然后后续插入变动较大,比较适合.这种只算局部排序,不涉及全场排序.