数据结构-堆的java实现

最大堆:所有根节点元素大于子节点元素

最小堆:所有根节点元素小于子节点元素

已知一节点位置为i,其左孩子2i+1,右孩子2i+2,父节点(i-1)/2


package moshi;

import java.util.Arrays;

/*
 * 数据结构->堆
 */
public class Heap {
	//最大堆-> 所有子树的根节点大于子节点的完全二叉树
	//最小堆-> 所有子树的根节点小于子节点的完全二叉树
	
	private int[] heap = new int[1024];
	private int length = -1;
	public void insert(int data){
		heap[++length] = data;
		//reBuidMaxHeap(heap,length);
	}
	
	
	//构建最大堆
	public void buildMaxHeap(){
		//叶子节点没有子节点不用重构堆
		for(int i=length/2;i>=0;i--){
			maxHeapFixed(heap,i,length);
		}
	}

	//从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2  
	//删除节点时,把根元素和最后的一个元素交换,并根据新交换的新根元素调整整个堆(从上到下沉降调整),所以此时i为0
	public void minHeapFixed(int arr[], int i, int n){
		//获取要调整的节点的值
		int temp = arr[i];
		int minChildIndex = 2*i+1;
		while(minChildIndex < n){
			//保证有右孩子并且右孩子比左孩子小
			if(minChildIndex+1 < n && arr[minChildIndex+1] < arr[minChildIndex]){
				minChildIndex++;
			}
			//根比左右孩子都小则结束循环
			if(arr[minChildIndex] >= temp){
				break;
			}
			//根比左和右大,用左、右的最小值覆盖根值,并定义新的根和孩子向下沉降递归
			arr[i] = arr[minChildIndex];
			i = minChildIndex;
			minChildIndex = 2*i+1;
		}
		//沉降找到了位置
		arr[i] = temp;
	}
	public void maxHeapFixed(int arr[], int i, int n){
		//获取要调整的节点的值
		int temp = arr[i];
		int minChildIndex = 2*i+1;
		while(minChildIndex < n){
			if(minChildIndex+1 < n && arr[minChildIndex+1] > arr[minChildIndex]){
				minChildIndex++;
			}
			if(arr[minChildIndex] <= temp){
				break;
			}
			arr[i] = arr[minChildIndex];
			i = minChildIndex;
			minChildIndex = 2*i+1;
		}
		arr[i] = temp;
	}
	
	public void 堆排序(){
		for(int i = length;i>=0;i--){
			int temp = heap[i];
			heap[i] = heap[0];
			heap[0] = temp;
			maxHeapFixed(heap,0,i);
		}
	}
	
	//添加新的元素后重排序成最小堆
	public void reBuidMinHeap(int[] heap,int index){
		//保存将要插入的值
		int temp = heap[index];
		//保存插入值的下标
		int tempIndex = index;
		//获取当前位置插入的根节点
		int rootIndex = (index-1)/2;
		while(rootIndex >=0 && tempIndex!=0){
			//要插入的值大于等于根节点->满足最小堆
			if(temp >= heap[rootIndex]){
				break;
			}
			//要插入的值比当前插入位置换算的根节点值小的话
			//根的值给当前位置
			heap[tempIndex] = heap[rootIndex];
			//在往上走,循环检测
			tempIndex = rootIndex;
			rootIndex = (tempIndex-1)/2;
		}
		//找到了应在的位置
		heap[tempIndex] = temp;
	}
	
	//添加新的元素后重排序成最大堆
	public void reBuidMaxHeap(int[] heap,int index){
		int temp = heap[index];
		int tempIndex = index;
		int rootIndex = (index-1)/2;
		while(rootIndex >= 0 && tempIndex!=0){
			if(heap[rootIndex] >= temp){
				break;
			}
			heap[tempIndex] = heap[rootIndex];
			tempIndex = rootIndex;
			rootIndex = (tempIndex-1)/2;
		}
		heap[tempIndex] = temp;
	}
	
	
	
	public int[] returnHeap(){
		int[] arr = new int[length+1];
		System.arraycopy(heap, 0, arr, 0, length+1);
		return arr;
	}
	public static void main(String[] args) {
		Heap heap = new Heap();
		int[] arr = {1,4,5,7,8,9,2,3,6};
		for(int i:arr){
			heap.insert(i);
		}
		//把加入的无序数组构建成最大堆
		heap.buildMaxHeap();
		heap.堆排序();
		System.out.println(Arrays.toString(heap.returnHeap()));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值