二叉堆

要实现插入和查找操作,可以用队列。普通的队列,先入先出,那么对于插入insert操作,是常数级的时间复杂度;而对于查找操作,则需要遍历整个队列,需要时间O(n);我们也可以在插入时保证队列的有序,那么插入操作的时间复杂度为O(n),而查找操作则是O(1)。

也可以用二叉查找树实现容器,进行插入和查找操作,时间复杂度均为O(lgn)。但是如果输入本身有序,会导致二叉查找树的深度急剧增大。而二叉平衡树AVL的实现代价又太大,插入和删除均需旋转以保证树的平衡,实现比较复杂。

那么,另外一种数据结构就是堆。对于堆,我们可以看做一颗完全二叉树。故对于节点i,它的左孩子序号为2*i,右孩子序号为2*i+1。由于这样的特性,所以我们可以简单的仅用数组即可以实现堆。

以下就是用JAVA语言实现小顶堆的JAVA代码,其中在删除节点时,每次都将其调整为小顶堆,从而保证输出是有序队列,非常方便。

package com.Algorithm.Heap;
/*
 * author:Tammy Pi
 * function:二叉堆,本代码实现的是小顶堆
 */
public class BinaryHeap {

	//存放元素的数组
	//由于堆相当于一颗完全二叉树
	//对于节点i,其左孩子为2*i,而右孩子为2*i+1,故可以简单通过数组实现
	private int[] n=new int[101];
	private int currentSize=0;
	
	//小顶堆插入数字
	public void insert(int i)
	{
		int hole=++currentSize;
		if(hole==1)
		{
			n[hole]=i;
			return;
		}
		for(;hole>1&&i<n[hole/2];hole=hole/2)
		{
			n[hole]=n[hole/2];
		}
		n[hole]=i;
	}
	//删除最小值
	public int deleteMin()
	{
		int temp=n[1];
		//首先用堆的最后一个元素取代它
		//堆中元素从1到currentSize
		n[1]=n[currentSize--];
        adjustDown(1);
        
		return temp;
	}
	public void adjustDown(int i)
	{
		int child;
		int hold=i;
		//调整后的最顶端
		int temp=n[1];
		for(;hold*2<=currentSize;hold=hold*2)
		{
			child=2*hold;
			if(child+1<=currentSize&&n[child+1]<n[child])
			{
				child++;
			}
			if(n[child]<n[hold])
			{
				int temp1=n[hold];
				n[hold]=n[child];
				n[child]=temp1;
			}
			else
			{
				break;
			}
		}
		n[currentSize+1]=temp;
	}
	public int[] getN() {
		return n;
	}

	public void setN(int[] n) {
		this.n = n;
	}

	public int getCurrentSize() {
		return currentSize;
	}

	public void setCurrentSize(int currentSize) {
		this.currentSize = currentSize;
	}

	//输出 
	public static void main(String[] args)
	{
		BinaryHeap heap=new BinaryHeap();
		heap.insert(3);
		heap.insert(1);
		heap.insert(2);
		heap.insert(1);
		heap.insert(2);
		
		for(int i=0;i<5;i++)
		{
			System.out.print(heap.deleteMin()+" ");
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值