堆排序

算法分析:

堆排序的思想是利用数据结构--。具体的实现细节: 
1. 构建一个最大堆。对于给定的包含有n个元素的数组A[n],构建一个最大堆,从最下层最右边的非终端结点开始构建,将它与其孩子进行比较和若有必要的互换,调整这个堆结构,使其满足最大堆的特性。当为了满足最大堆特性时,堆结构发生变化,此时递归调整对应的子树。 
2. 堆排序算法,每次取出该最大堆的根节点,同时,取最末尾的叶子节点来作为根节点,从此根节点开始调整堆,使其满足最大堆的特性。 
3. 重复上一步操作,直到堆的大小由n个元素降到2个。 
4. gif 演示:http://upload.wikimedia.org/wikipedia/commons/4/4d/Heapsort-example.gif (来自wikipedia) 

时间复杂度分析:O(NlogN)

在构建堆的过程中,因为我们是完全二叉树从最下层最右边的非终端结点开始构建,将它与其孩子进行比较和若有必要的互换,对于每个非终端结点来说,其实最多进行两次比较和互换操作,因此整个构建堆的时间复杂度为O(n)。

在正式排序时,第i次取堆顶记录重建堆需要用O(logi)的时间(完全二叉树的某个结点到根结点的距离为.log2i.+1),并且需要取n-1次堆顶记录,因此,重建堆的时间复杂度为O(nlogn)。

所以总体来说,堆排序的时间复杂度为O(nlogn)。由于堆排序对原始记录的排序状态并不敏感,因此它无论是最好、最坏和平均时间复杂度均为O(nlogn)。这在性能上显然要远远好过于冒泡、简单选择、直接插入的O(n2)的时间复杂度了。

空间复杂度上,它只有一个用来交换的暂存单元,也非常的不错。不过由于记录的比较与交换是跳跃式进行,因此堆排序也是一种不稳定的排序方法。

public class HeapSort
{
	public int[] heap;
	public int heapsize;
	public HeapSort(int[] array)
	{
		this.heap = array;
		heapsize = array.length;
	}
	
	//建堆,从heapsize/2-1处开始
	public void buildMaxHeap()
	{
		for(int i = heapsize/2 - 1; i >= 0; i --)
		{
			maxify(i);
		}
	}
	//调整,递归
	public void maxify(int i)
	{
		int left = 2*i+1;
		int right = 2*i+2;
		int max = i;
		if(left < heapsize && heap[left] > heap[i])
		{
			max = left;
		}
		if(right < heapsize && heap[right] > heap[max])
		{
			max = right;
		}
		if(max == i)
		{
			return ;
		}
		int tmp = heap[i];
		heap[i] = heap[max];
		heap[max] = tmp;
		maxify(max);
	}
	//堆排序
	public void heapSort()
	{
		for(int i = 0; i < heap.length; i ++)
		{
			int tmp = heap[0];
			heap[0] = heap[heapsize - 1];
			heap[heapsize - 1] = tmp;
			heapsize --;
			maxify(0);
		}
	}
	
	public static void main(String[] args) 
	{
		int[] a = {1,2,3,4,5,6,7};
		HeapSort hs = new HeapSort(a);
		hs.buildMaxHeap();
		for (int i : a)
		{
			System.out.print(i + " ");
		}
		System.out.println();
		hs.heapSort();
		for(int i : a)
		{
			System.out.print(i + " ");
		}
	}
}
原文地址:https://www.cnblogs.com/masterlibin/p/5741195.html