堆排序

堆排序是一种选择排序

一,二叉堆

二叉堆是一棵完全二叉树,除底层外都填满,底层元素从左向右填入,二叉堆有两种:最大堆和最小堆。最大堆:父结点的键值总是大于或等于任何一个子节点的键值;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。二叉堆简称为堆。

堆可以用数组存储。

	private int[] heapArray;
		private int maxSize;// 数组长度
		private int heapSize;// 存放在数组中的堆元素个数


i结点的父结点为(i-1)/2  ,左子结点为2i+1,右子结点为2i+2


对于数组A[],长度为n,子数组A[n/2],......,A[n-1]都是树中的叶子。

在堆排序算法中我们使用最大堆,最小堆通常用于构造优先级队列。

二,保持最大堆的性质

如果根不是最大值,但是它的左子树和右子树都是最大堆,就需要把根元素下降到合适的位置,使整棵树调整成最大堆。

trickleDown()方法

比较根元素和最大的孩子间谁大,如果根元素小,就交换二者,层层下降,直到根元素大于最大的孩子为止。

public void trickleDown(int index) {
			int largerChild;
			int top=heapArray[index];
			while(index<(heapSize>>1)){//该结点不是叶子,至少有一个孩子
				int leftChild=2*index+1;
				int rightChild=leftChild+1;
				if(rightChild<heapSize&&heapArray[leftChild]<heapArray[rightChild])//如果右孩子存在并且比左孩子大
					largerChild=rightChild;
				else
					largerChild=leftChild;
				if(top>=heapArray[largerChild])//如果top比最大的孩子大,跳出循环
					break;
				heapArray[index]=heapArray[largerChild];//将最大的孩子提升上去
				index=largerChild;//指针下降				
			}
			heapArray[index]=top;//将根赋值给索引处
		}

三,建立一个最大堆

叶子A[n/2],......,A[n-1]都可以看做正确的堆。

因此从A[n/2-1]开始,倒退到A[0],对这些不是叶子的结点依次用trickleDown()方法,将堆调整成最大堆。

		public Heap(int[] arrays) {
			maxSize = arrays.length;
			heapSize = maxSize;
			heapArray = arrays;
			for(int i=(maxSize >> 1)-1;i>=0;i--){
				trickleDown(i);
			}
		}

四,堆排序算法

排序结束后数组元素从小到大排列,而最大堆的根是最大元素。因此可以将堆顶根元素和堆的最后一个元素互换,来使最大元素到达最终位置,从堆中去除互换后的最后一个元素,将堆调整成最大堆。循环执行上述步骤,直到排序完毕。

上述步骤等价于先去除堆顶元素,调整最大堆,然后将被去除的堆顶元素赋值给堆后边的元素。

	public HeapSort(int[] arrays) {
		Heap mHeap=new Heap(arrays);//建立最大堆
		for(int i=arrays.length-1;i>=0;i--){
			int node=mHeap.remove();//去除堆顶元素,调整最大堆
			mHeap.insertAt(i,node);//将被去除的堆顶元素赋值给堆后边的元素。
		}				
	} 


		public void insertAt(int index, int node) {
			// TODO 自动生成的方法存根
			heapArray[index]=node;
		}

		public int remove() {
			// TODO 自动生成的方法存根
			int root=heapArray[0];
			heapArray[0]=heapArray[--heapSize];//将堆的最后一个元素的值赋值给heapArray[0]
			trickleDown(0);//调整堆
			return root;
		}

trickleDown方法的最差运行时间是O(logN),remove方法也是

堆排序算法的最差运行时间是O(NlogN),平均时间也是。堆排序算法比快速排序略慢,但是好处是对初始数据的分布不敏感,快速排序的最差运行时间是O(N^2)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值