二叉堆的理解和实现(java)

其实在写二叉堆实现的时候,已经在堆排序中了解了二叉堆,所以在这里不再详细讲解二叉堆的性质,有兴趣的可以看一看这里:堆排序(最大堆)的理解和实现(Java)

最大堆

代码实现:

package 二叉堆;

import java.util.ArrayList;

/**
 * 最大堆
 * @author lishanlei
 *
 */
public class MaxHeap<T extends Comparable<T>> {

	
	//用List来存储堆
	public ArrayList<T> mHeap;

	public MaxHeap() {
		this.mHeap = new ArrayList<T>();
	}


	/**
	 * 最大堆的上泛
	 * 数组实现的堆中,第n个节点的左孩子的索引值是(2n + 1),第n个节点的右孩子的索引值为(2n + 2)
	 * @param start 被上调节点的起始位置(一般是数组中最后一个元素的索引)
	 */
	private void filterup(int start) {

		int current = start;               //当前节点的位置
		int father = (current - 1) / 2;    //当前节点父节点的位置
		T cData = this.mHeap.get(current);  //当前节点的值
		while(current > 0) {
			int tmp = this.mHeap.get(father).compareTo(cData);
			if(tmp > 0) {
				break;
			}
			else {
				this.mHeap.set(current, this.mHeap.get(father));
				current = father;
				father = (father - 1) / 2;
			}
		}
		this.mHeap.set(current, cData);
	}

	/**
	 * 最大堆的下泛调整
	 * @param start 被下调节点的索引值(一般为0,表示从第一个开始)
	 * @param end 截至范围(一般为数组中最后一个元素的索引)
	 */
	private void filterdown(int start, int end) {
		int current = start;            //当前节点的位置
		int left = (current * 2) + 1;   //左孩子节点的位置
		T cData = this.mHeap.get(current);  //当前节点的值
		while(left < end) {
			int cmp = this.mHeap.get(left).compareTo(this.mHeap.get(left + 1));
			if(left < end && cmp < 0) {
				++left;
			}
			cmp = cData.compareTo(this.mHeap.get(left));
			if(cmp > 0) {
				break;
			}
			else {
				this.mHeap.set(current, this.mHeap.get(left));
				current = left;
				left =(2 * left) + 1;
			}
		}
		this.mHeap.set(current, cData);
	}


	/**
	 * 二叉树的插入操作
	 * @param data
	 */
	public void insert(T data) {
		int size = this.mHeap.size();
		this.mHeap.add(data);
		this.filterup(size);
	}


	/**
	 * 二叉树的删除操作
	 * @param data
	 * @return
	 */
	public int remove(T data) {
		if(this.mHeap.isEmpty() == true) {
			return -1;
		}

		int index = this.mHeap.indexOf(data);
		if(index == -1) {
			return -1;
		}

		int size = this.mHeap.size();
		this.mHeap.set(index, this.mHeap.get(size - 1));
		this.mHeap.remove(size - 1);
		if(this.mHeap.size() > 1) {
			this.filterdown(index, this.mHeap.size() - 1);
		}
		return 1;
	}

	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < this.mHeap.size(); i++) {
			sb.append(this.mHeap.get(i) + ", ");
		}
		return sb.toString();
	}

	public static void main(String[] args) {
		int i;
		int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80};
		MaxHeap<Integer> tree=new MaxHeap<Integer>();

		System.out.printf("== 依次添加: ");
		for(i=0; i<a.length; i++) {
			System.out.printf("%d ", a[i]);
			tree.insert(a[i]);
		}

		System.out.printf("\n== 最 大 堆: %s", tree);

		i=85;
		tree.insert(i);
		System.out.printf("\n== 添加元素: %d", i);
		System.out.printf("\n== 最 大 堆: %s", tree);

		i=90;
		tree.remove(i);
		System.out.printf("\n== 删除元素: %d", i);
		System.out.printf("\n== 最 大 堆: %s", tree);
		System.out.printf("\n");
	}

}

测试:

== 依次添加: 10 40 30 60 90 70 20 50 80 
== 最 大 堆: 90, 80, 70, 60, 40, 30, 20, 10, 50, 
== 添加元素: 85
== 最 大 堆: 90, 85, 70, 60, 80, 30, 20, 10, 50, 40, 
== 删除元素: 90
== 最 大 堆: 85, 80, 70, 60, 40, 30, 20, 10, 50, 

最小堆

代码实现:

package 二叉堆;

import java.util.ArrayList;

/**
 * 最小堆
 * @author lishanlei
 *
 * @param <T>
 */
public class MinHeap<T extends Comparable<T>> {

	public ArrayList<T> mHeap;

	public MinHeap() {
		this.mHeap = new ArrayList<T>();
	}


	/**
	 * 最小堆的上泛
	 * @param start
	 */
	public void filterup(int start) {
		int current = start;
		int father = (current - 1) / 2;
		T cData = this.mHeap.get(current);
		while(current > 0) {
			int cmp = this.mHeap.get(father).compareTo(cData);
			if(cmp <= 0) {
				break;
			}
			else {
				this.mHeap.set(current, this.mHeap.get(father));
				current = father;
				father = (father - 1) / 2;
			}
		}
		this.mHeap.set(current, cData);

	}


	/**
	 * 插入数据到最小堆
	 * @param data
	 */
	public void insert(T data) {
		int size = this.mHeap.size();
		this.mHeap.add(data);
		this.filterup(size);
	}

	/**
	 * 最小堆的下泛
	 * @param start
	 * @param end
	 */
	public void filterdown(int start, int end) {
		int current = start;
		int left = (2 * current) + 1;
		T cData = this.mHeap.get(current);
		while(left <= end) {
			int tmp = this.mHeap.get(left).compareTo(this.mHeap.get(left + 1));
			if(left < end && tmp > 0) {
				left++;
			}

			tmp = cData.compareTo(this.mHeap.get(left));

			if(tmp <= 0) {
				break;
			}
			else {
				this.mHeap.set(current, this.mHeap.get(left));
				current = left;
				left = 2 * left + 1;
			}
		}
		this.mHeap.set(current, cData);
	}

	public int remove(T data) {
		if(this.mHeap.isEmpty() == true) {
			return -1;
		}

		int index = this.mHeap.indexOf(data);
		if(index == -1) {
			return -1;
		}

		int size = this.mHeap.size();
		this.mHeap.set(index, this.mHeap.get(size - 1));
		this.mHeap.remove(size - 1);
		if(this.mHeap.size() > 1) {
			this.filterdown(index, this.mHeap.size() - 1);
		}

		return 1;
	}

	//打印堆
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (int i=0; i<mHeap.size(); i++)
			sb.append(mHeap.get(i) +" ");

		return sb.toString();
	}

	public static void main(String[] args) {
		int i;
		int a[] = {80, 40, 30, 60, 90, 70, 10, 50, 20};
		MinHeap<Integer> tree=new MinHeap<Integer>();

		System.out.printf("== 依次添加: ");
		for(i=0; i<a.length; i++) {
			System.out.printf("%d ", a[i]);
			tree.insert(a[i]);
		}

		System.out.printf("\n== 最 小 堆: %s", tree);

		i=15;
		tree.insert(i);
		System.out.printf("\n== 添加元素: %d", i);
		System.out.printf("\n== 最 小 堆: %s", tree);

		i=10;
		tree.remove(i);
		System.out.printf("\n== 删除元素: %d", i);
		System.out.printf("\n== 最 小 堆: %s", tree);
		System.out.printf("\n");
	}
}

测试:

== 依次添加: 80 40 30 60 90 70 10 50 20 
== 最 小 堆: 10 20 30 50 90 70 40 80 60 
== 添加元素: 15
== 最 小 堆: 10 15 30 50 20 70 40 80 60 90 
== 删除元素: 10
== 最 小 堆: 15 20 30 50 90 70 40 80 60 

参考:https://www.cnblogs.com/skywang12345/p/3610390.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值