java:实现堆结构和堆排序

//堆结构:大根堆------堆排序
//PriorityQueue<Integer> heap = new PriorityQueue<>();    //系统默认的优先级队列(即系统默认堆-小根堆)
//heap.add(5); heap.add(7);    //添加5.7元素
//while(!heap.isEmpty){ System.out.print( HEAP.POLL() ); }     //打印出所有数



public static class MyMaxHeap{
	private int[] heap;  //堆-用数组形式表达
	private int limit;    //
	private int heapSize;     //记录数组元素的长度

	//有参构造器
	public MyMaxHeap( int limit) {
		heap =new int[limit];
		this.limit = limit;
		heapSize = 0;
	}
	
	
	//堆排序-大根堆有规律,但没有全局排序,于是我们将第n大值向后与倒数n数交换 :O(N*logN-n个数持续n遍,每遍最多执行2logN次操作,)
	public void heapSort(int[] arr) {
		if(arr == null || arr.length<2)return;      //元素值过少
		
		
		for(int i=0;i<arr.length;i++) {     //将每一个元素视为新添加的元素进行大根堆调整
			heapInsert(arr,i);
		}
		/*当用户不需要全局排序、只需要大根堆时,可以直接用此for代替上一个for。从最末尾位置开始,判定是否需要下沉,直到0索引结束:O(N)
		for(int i=arr.length-1;i>=0;i--) {     
			heapify(arr,i,arr.length);
		}
		*/
		
		
		int heapSize = arr.length;           //赋值当前数组长度
		swap(arr,0,--heapSize);              //交换0索引最大值和最末尾值,并且进行元素--操作(即将大值放在数组末尾,同时固定已经放好的大值、不再修改)
		while(heapSize > 0) {                 //一直持续到没有元素
			heapify(arr,0,heapSize);          //每次将最大值、最末尾位置值交换后,就进行heapify-堆结构整理方法
			swap(arr,0,--heapSize);
		}
	}
	
	
	
	
	//判断数组元素长度是否为0,是否为Limit(即数组的内存长度)
	public boolean isEmpty() {
		return heapSize == 0;
	}
	public boolean isFull() {
		return heapSize == limit;
	}
	
	//判定还有没有内存空间
	public void push(int value) {
		if(heapSize == limit) {       //即数组元素长度达到内存空间长度,输出内存满了
			throw new RuntimeException("heap is full");
		}
		heap[heapSize] = value;    //即内存空间还有,就将输入的value作为第heapSize个索引输入
		heapInsert(heap,heapSize++);    //调用heapInsert方法,对输入的value在大根堆中排序的一部分
	}
	//
	public void pop() {
		int max = heap[0];             //找到数组-堆的最大值-索引0
		System.out.println(max);
		swap(heap,0,--heapSize);   		//将索引0的数和最后位 heapSize进行交换,同时数组长度-1以删除最大值
		heapify(heap,0,heapSize);       //将已经是0索引的heapSize-1值(相对最小的值)递归的向子节点比较、交换
	}
	
	//index即输入项的节点位置,(index-1)/2即父节点,
	public void heapInsert(int[] arr,int index) {
		while(arr[index] > arr[(index-1)>>1]) {   //如果子节点值>父节点值,就交换位置(判定条件也会排除:index处于最高父节点,这时(index-1)/2等于index)
			swap(arr,index,(index-1)>>1);
			index = (index-1)>>1;           //然后将父节点位置赋值给index
		}
	}
	

	//将已经是0索引的heapSize-1值(相对最小的值)递归的向子节点比较、交换---即下沉:当没有子节点 或 没有更小值的子节点
	public void heapify(int[] arr,int index,int heapSize) {      //index:现在的位置
		int left = index * 2 +1;          //子左节点left,
		while(left<heapSize) {            //即还未到最小的子节点,或者没有子节点了,即有left左节点且不越界
			int largest = left +1 < heapSize && arr[left+1] >arr[left]? left+1: left;        //有右子节点,且右子节点>左子节点,就换右子节点,否则换子左节点
			//上下代码-将index(父节点)、left(子左节点)、left+1(右子节点)进行判断,谁大赋值给 largest
			largest = arr[largest] > arr[index] ? largest : index ;           //将子节点大的那个跟父节点index进行判断,子节点大就换
			if(largest == index) {              //即index父节点更大,直接退出
				break;
			}
			//子节点更大
			swap(arr,largest,index);   //交换largest 和 index
			index = largest;           //将largest 赋值给 index
			left = index *2 +1;        //下一个子节点
		}
	}
}
//数组元素交换
public static void swap(int[] arr,int i,int j) {
	int temp;
	temp = arr[i];
	arr[i] = arr[j];
	arr[j] = temp;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值