堆排序算法

       上一篇文章讲到了最大堆最小堆算法,今天又用最大堆写了个堆排序。正序使用最大堆,倒序使用最小堆。堆排序是简单选择排序算法的一种改进排序算法,时间复杂度为O(nlogn)。以正序为例,该算法的思想是利用数组构建最大堆,每次将最后一个结点与堆顶互换,这样最大的数就排到了数组的尾端。再用还未排好位置的其他结点重构最大堆,堆顶再与末结点互换。。。以此循环直到所有结点都排在正确的位置。

 

/**
 * 堆排序
 * @author dwl
 *
 */
public class HeapSort {
	
	private int[] data;
	
	public HeapSort(int[] data){
		this.data = data;
		//从最后一个拥有子结点的结点开始重构最大堆
		for(int i =data.length/2-1;i>=0;i--){
			buildHeap(i, data.length);
		}
	}
	
	/**
	 * 构建大顶堆
	 * @param i 父结点位置
	 * @param last 可交换子节点位置
	 */
	private void buildHeap(int i,int last){
		
		int temp = 0;
		int left =left(i);
		int right = right(i);
		//左右孩子都参与可重构
		if(right<last){
			//获取左右孩子中较大数的下标
			temp = max(left, right);
			if(data[temp]>data[i]){
				//交换父子结点
				swap(i, temp);
				//交换结点后可能对原子结点的子树产生影响,重构该子结点的子数
				buildHeap(temp, last);	
			}			
		}else if(left<last){//只有左孩子可以参加重构
			//满足条件直接交换,无需重构
			if(data[left]>data[i])
				swap(i, left);
			
		}			
	}
	
	/**
	 * 根据父结点下标获取
	 * 左孩子下标
	 * @param i
	 * @return
	 */
	private int left(int i){
		return ((i+1)<<1)-1;	
	}
	
	/**
	 * 根据父结点下标获取
	 * 右孩子下标
	 * @param i
	 * @return
	 */
	private int right(int i){
		return (i+1)<<1;
	}
	
	/**
	 * 交换两个结点
	 * @param i
	 * @param j
	 */
	private void swap(int i,int j){
		
		int temp = data[i];
		data[i] = data[j];
		data[j] = temp;
		
	}
	
	/**
	 * 返回连个结点中较大的下标
	 * @param i
	 * @param j
	 * @return
	 */
	private int max(int i,int j){
		if(data[i]>=data[j])
			return i;
		return j;
		
	}
	

	/**
	 * 最后一个结点与根结点交换,重构该结点前的其他结点
	 * @param last
	 */
	public void changeRootLast(int last){
		int temp = data[0];
		data[0] = data[last];
		data[last] = temp;
		//最后一次不再重构堆
		if(last>1){
			buildHeap(0, last-1);
		}
		

		
		
	}
	
	/**
	 * 获取数组
	 * @return
	 */
	public int[] getData(){
		return data;
	}
	
	
	/**
	 * 获取排序后的数组
	 * @return
	 */
	public int[] getSort(){
	    //循环将堆顶放入i的位置
		for(int i = data.length-1;i>0;i--){
			changeRootLast(i);
		}
		
		return data;
		
	}
	
	public static void main(String[] args) {
		int[] data = {5,23,4,1,83,3,6,34,7};
		HeapSort heap = new HeapSort(data);
		int[] result =heap.getData();
		//输出初始堆
		for(int n:result){
			System.out.print(n+";");
		}
		
		int[] sort = heap.getSort();
		System.out.println();
		//输出排好序的数组
		for(int n:sort){
			System.out.print(n+";");
		}
		
		
		
		
	}

}


测试结果如下图:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值