小根堆
小根堆是指堆顶的值最小的树,小根堆的每个子节点的值都比父节点的值大,也因为这样,一般用来在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