java实现小顶堆 在指定数据中找出前n大的数

小顶堆:

      我们利用的特性:每个节点都比左右孩子小

      图示:

      取数组前n个数,构成小顶堆

     然后从数组里面获取数据,如果比堆顶小,直接抛弃,如果比堆顶大,就替换堆顶,并调整堆,使堆始终满足小顶堆的特性

    93比18大,替换18

    调整堆

然后依次处理下一个数44

对数组内的数调整完成后,前n个大的数 就在小顶堆里面了

平均时间复杂度为Ο(nlogn)

代码实现:

import java.util.Arrays;

public class TopN {

	/**
	 * 父节点
	 */
	private int parent(int n) {
		return (n - 1) / 2;
	}

	/**
	 * 左孩子
	 */
	private int left(int n) {
		return 2 * n + 1;
	}

	/**
	 * 右孩子
	 */
	private int right(int n) {
		return 2 * n + 2;
	}

	/**
	 * 构建堆
	 * 
	 * @param n
	 *            构建包含n个节点的堆
	 * @param data
	 *            构建堆的数据
	 */
	public void buildHeap(int n, int[] data) {
		for (int i = 1; i < n; i++) {
			int t = i;

			// 调整堆
			while (t != 0 && data[parent(t)] > data[t]) {
				int temp = data[t];
				data[t] = data[parent(t)];
				data[parent(t)] = temp;

				t = parent(t);

			}
		}
	}

	/**
	 * 调整堆
	 * 
	 * @param i
	 *            被调整的数在数据中的下标
	 * @param n
	 *            从第n个数开始 不在之前构建的堆里面
	 * @param data
	 *            需要被调整的数据
	 */
	public void adjust(int i, int n, int[] data) {
		// 被调整的数小于堆顶 不做任何操作
		if (data[i] <= data[0])
			return;

		// 被调整的数 先和堆顶的数交换
		int temp = data[i];
		data[i] = data[0];
		data[0] = temp;

		// 和堆顶交换后的数 和左右子树判断值 再决定和谁交换
		int t = 0;

		while (left(t) < n && data[left(t)] < data[t] || right(t) < n && data[right(t)] < data[t]) {
			// 右孩子比较小,交换
			if (right(t) < n && data[right(t)] < data[left(t)]) {
				temp = data[t];
				data[t] = data[right(t)];
				data[right(t)] = temp;

				t = right(t);
			} else {
				// 交换左孩子
				temp = data[t];
				data[t] = data[left(t)];
				data[left(t)] = temp;

				t = left(t);
			}
		}
	}

	/**
	 * 找到前n个大的数
	 * 
	 * @param n
	 * @param data
	 */
	public void findTopN(int n, int[] data) {
		// 先构建堆
		buildHeap(n, data);

		// 堆n个数之后的数进行调整
		for (int i = n; i < data.length; i++) {
			adjust(i, n, data);
		}
	}

	public static void main(String[] args) {
		int[] data = { 99, 66, 23, 65, 12, 56, 1, 67, 88, 23, 567, 123, 321, 231, 342, 556, 666, 731, 466, 29 };

		System.out.println("构建数组前的数组为:" + Arrays.toString(data));

		TopN top = new TopN();
		top.buildHeap(7, data);

		System.out.println("构建数组后的数组为:" + Arrays.toString(data));

		top.findTopN(7, data);
		System.out.println("findTopN的数组为:" + Arrays.toString(data));
	}
}

测试结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值