java实现堆排序(2016年腾讯内推笔试的一道算法题)

/**这是2016年腾讯微信部web开发内推笔试的一道题
 * 题目情景:有一个公司有若干员工,要求设计一个签到系统来记录员工的签到顺序,
 *          并能够在nlogn的时间复杂度内利用尽可能少的辅助空间将签到的员工按照员工id进行排序。
 * 思路:在所有算法中只有堆排序和归并排序能够达到时间复杂度的要求,而堆排序对空间的要求
 *       又要优于归并排序,所以最后采用了堆排序来实现。*/

/*构建员工模型*/
class Staff{
	int id;//员工id
	Staff(int id ){
		this.id=id;
	}
	public void setId(int id){
		this.id=id;
	}
	public int getId(){
		return this.id;
	}
	
}
public class StaffSort {
	private Staff[] log; // 记录员工序号序列
	private int totalStaff; // 员工总人数
	private int currentStaff; //此时员工人数

	public StaffSort(int totalStaff) {
		// TODO Auto-generated constructor stub
		this.totalStaff=totalStaff;
		currentStaff=0;
		log=new Staff[totalStaff];
	}

	/*
	 * @author Sam
	 * @param id
	 * @return isSuccess
	 * Described 员工签到*/
	public boolean check(int id) {
		Staff newStaff = new Staff(id);
		log[currentStaff] = newStaff;
		trickleUp(currentStaff++);
		return true;
	}

	/*
	 * @author Sam
	 * @param index
	 * @return isSuccess
	 * Described 向上调整堆模型,使各点的值不大于其双亲结点的值*/
	public void trickleUp(int index) {
		int parent = (index - 1) / 2;
		Staff bottom = log[index];

		while (index > 0 && log[parent].getId() < bottom.getId()) {
			log[index] = log[parent]; 
			index = parent;
			parent = (parent - 1) / 2;
		}
		log[index] = bottom; 
	}

	/*
	 * @author Sam
	 * @param 
	 * @return root
	 * Described 获取并删除堆顶*/
	public Staff remove() {
		Staff root = log[0];
		log[0] = log[--currentStaff];
		trickleDown(0);
		return root;
	}

	/*
	 * @author Sam
	 * @param index
	 * @return 
	 * Described 向下调整堆结构,是堆顶元素不小于孩子结点的值*/
	public void trickleDown(int index) {
		int largeChild;
		Staff top = log[index]; 
		while (index < currentStaff / 2) { 
			int leftChild = 2 * index + 1;
			int rightChild = leftChild + 1;

			if (rightChild < currentStaff
					&& log[leftChild].getId() < log[rightChild]
							.getId()) {
				largeChild = rightChild;
			} else {
				largeChild = leftChild;
			}

			if (top.getId() >= log[largeChild].getId()) {
				break;
			}

			log[index] = log[largeChild]; 
			index = largeChild; 
		}
		log[index] = top;
	}

	/*
	 * @author Sam
	 * @param args
	 * @return 
	 * Described 打印排序后的结果*/
	public static void main(String[]args){
		int[] staffs=new int[]{1,3,5,2,12,10,15};
		StaffSort ss=new StaffSort(50);
		for(int i=0;i<staffs.length;i++){
			ss.check(staffs[i]);
		}
		while (ss.currentStaff!=0) {
			System.out.print(ss.remove().getId()+" ");
			
		}
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值