java 大根堆_大根堆Java实现:

使用树组表示的完全二叉树的下表有如下规律:

0

1 2

3 4 5 6

7 8 ...

其中针对于k节点,其父节点是 (k-1)/2 (注意: 0节点除外)

对于k节点,其两个儿子节点分布是: left = 2*k + 1 ; right = 2 *k + 2;

大根堆两个主要算法:

向上调整算法: 主要用于插入新元数的时候;

向下调整算法: 用于从数组创建一个大根堆,或者删除元素的时候;

最后一个节点是heapSize -1 那么最后一个节点的父节点就是最后一个非叶子节点:(完全二叉树规律);

最后一个非叶子节点是(heapSize - 2)/2;

package BaseDataStructure;

import java.util.Arrays;

public class Heap {

int[] arr = new int[10];

int heapSize = 0;

public void push(int value) {

arr[heapSize++] = value;

adjustUp((heapSize-2)/2);

}

public void poll(){

swap(0, heapSize-1);

heapSize --;

adjustDown(0);

}

// 构建一个最大堆的过程:就是从后往前

// 针对每个非叶子节点,做向下调整算

// 参数是:将传如数组,构建大根堆。

public void buildMaxHeap(int[] _arr){

arr = _arr;

heapSize = _arr.length;

// 找到非叶子节点,然后向下调整;

for(int i = (arr.length -2)/2; i >= 0; i --){

adjustDown(i);

}

}

// 向下调整算法

public void adjustDown(int k){

// 非叶子节点,不用向下调整。

// 判断叶子节点:(堆大小是1 或 就一般的最后一个节点的父节点之后的节点都是叶子)

if(heapSize == 1 || k > (heapSize-2)/2 )

return;

int left = 2*k +1, right = 2 * k + 2, largest = left;

if(right < heapSize && arr[right] > arr[left]){

largest = right;

}

if(arr[largest] > arr[k]){

swap(largest, k);

adjustDown(largest);

}

}

// 向上调整算法

public void adjustUp(int k){

if(k < 0)

return;

int left = 2 * k + 1, right = 2 * k +2, largest = left;

if(right < heapSize && arr[right] > arr[left]){

largest = right;

}

if(arr[largest] > arr[k]){

swap(largest, k);

adjustUp((k-1)/2);

}

}

void swap(int i, int j){

int tmp = arr[i];

arr[i] = arr[j];

arr[j] = tmp;

}

// 排序只需要一直删除,堆顶元素, 放到堆末尾;

// 大根堆,就能进行从小到大排序。

void sort(){

for(int i = 0; i < arr.length; i++){

poll();

}

}

}

import java.util.Arrays;

public class TestDemo{

public static void main(String[] args) {

Heap heap = new Heap();

heap.buildMaxHeap( new int[]{3,4,5,6,9} );

System.out.println( Arrays.toString(heap.arr) );

heap.sort();

System.out.println( Arrays.toString(heap.arr ));

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值