手写java程序_手写最大堆(Java实现)

最大堆

最大堆和最小堆是二叉堆的两种形式。

最大堆:根结点的键值是所有堆结点键值中最大者,且每个结点的值都比其孩子的值大。

最小堆:根结点的键值是所有堆结点键值中最小者,且每个结点的值都比其孩子的值小。

最大堆的父元素与子元素的索引有如下关系

在最大堆中,设根节点索引从1开始,当父节点索引为i时,左孩子节点2*i , 右孩子索引2*i+1。

实现最大堆

定义最大堆的数据结构和构造函数

堆中数据的存储我们可以使用数组来实现,非常方便。

public class MaxHeap {

private int data[]; //存放堆数据的数组

private int size; //当前堆的大小

private int capacity; //堆的最大容量

public MaxHeap(int maxSize){

//数组索引为0的位置不放元素

data = new int[maxSize+1];

this.size = 0;

this.capacity = maxSize;

}

}

向堆里面插入元素

向堆里插入元素,首先将数据放到数据的最后一个位置,然后通过与其父元素比较,不断上移,直到该元素处于正确的位置。

//向堆里面插入元素

public void insert(int d){

if(size == capacity){

System.out.println("堆已满!");

return;

}

//索引为0的位置不存放元素

data[size+1] = d;

size++;

//插入在最后的元素上移方法

shiftUp(size);

}

//堆插入元素时的元素上移

private void shiftUp(int i) {

//数组可能越界问题始终不能忽视

//当此元素比父元素大时,交换这两个元素位置

while(i > 1 && data[i] > data[i/2]){

int t = data[i];

data[i] = data[i/2];

data[i/2] = t;

i /= 2;

}

}

删除堆中的最大元素

最大堆删除操作只能删除最大元素,具体做法时将最后一个元素放到第一个元素位置(替换最大元素),然后将这个元素不断下移到恰当位置,下面定义的shiftDown就是元素下移的方法。

//删除堆的最大元素

public int deleteMax(){

if(size == 0){

System.out.println("堆已经是空的了!");

return -1;

}

int t = data[1];

//将最后一个元素放到第一个元素位置

data[1] = data[size];

size--;

//然后将第一个元素下移到适当位置

shiftDown(1);

return t;

}

//堆删除元素时的元素下移

private void shiftDown(int i) {

// TODO Auto-generated method stub

while(2*i <= size){

// 将要将data[i]与data[j]交换

int j = 2*i;

// 让j指向他的孩子结点中的大的那一个

if(j+1 <= size && data[j] < data[j+1]){

j += 1;

}

if(data[i] > data[j])

break;

//元素下移

int t = data[i];

data[i] = data[j];

data[j] = t;

i = j;

}

}

堆排序

先将数组中的元素存放堆中去,然后依次删除取出堆中的最大元素就能实现堆排序

//堆排序

public void heapSort(int arr[],MaxHeap heap){

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

heap.insert(arr[i]);

}

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

arr[i] = heap.deleteMax();

}

}

堆排序优化

上面的那个堆排序需要先将数组中的数存到堆中,这里的时间复杂度是n(log2n),可以通过改变建堆的过程从而将建堆的时间复杂度变为O(n)级别。

使用heapify建堆:

public MaxHeap(int arr[],int maxSize){

this.data = new int[maxSize+1];

this.capacity = maxSize;

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

data[i+1] = arr[i];

}

this.size = arr.length;

for(int i = size; i >= 1; i--){

shiftDown(i);

}

}

这里能够提高效率是因为,从最后的元素开始shiftDown,实际上差不多有一半的元素不需要移动,从而节省了时间。改进后的堆排序代码为:

//bottom-up堆排序O(n)+O(nlog2n)

public void heapSort2(int arr[]){

MaxHeap maxHeap = new MaxHeap(arr,100);

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

arr[i] = maxHeap.deleteMax();

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值