标签:
算法分析:
堆排序的思想是利用数据结构--堆。具体的实现细节:
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 + " ");
}
}
}
标签:
原文地址:http://www.cnblogs.com/masterlibin/p/5741195.html