您的位置:首页 > 其它

堆排序(heapsort)

2012-05-06 14:27 387 查看
堆排序的运行时间为Θ(nlgn),它是一种原地排序算法:在任何时候,数组中只有常数个元素存储在输入数组以外;

对数据结构是一种数组对象,它可以被视为一棵完全二叉树。树中得每个结点与数组中存放该结点值的那个元素对应。

树的每一层都是填满的,最后一层可能除外,表示堆的数组A是一个具有两个属性的对象:length[A]是数组中的元素

个数,heap-size[A]是存放A中的堆元素个数。

给定某个结点的下标 i , 其父结点PARENT(i),左儿子LEFT(i)和右儿子RIGHT(i)的下标可以计算出来:

PARENT(i)

  return i/2

LEFT(i)

  return 2 * i

RIGHT(i)

  return 2 * i + 1

最大堆是指除了根以外的每个结点 i,有 A[PARENT(i)] >= A[i]

最小堆是指除了根以外的每个结点 i,有 A[PARENT(i)] <= A[i]

在堆排序算法中使用的是最大堆。

保持堆的性质 MAX- HEAPIFY 过程:

MAX-HEAPIFY(A, i)
  l ← LEFT(i)
  r ← RIGHT(i)
  if l <= heap-size[A] and A[l] > A[i]
    then largest ← l
    else largest ← i
  if r <= heap-size[A] and A[r] > A[largest]
    then largest ← r
  if largest != i

    then exchange A[i] ↔ A[largest]
      MAX-HEAPIFY(A, largest)


BUILD-MAX-HEAP过程:

BUILD-MAX-HEAP(A)
  heap-size(A) ← length[A]
  for i ← length[A]/2 downto 1
    do MAX-HEAPIFY(A, i)


堆排序算法:

HEAPSORT(A)
  BUILD-MAX-HEAP(A)
  for i ← length[A] downto 2
    do exchange A[1] ↔ A[i]
      heap-size[A] ← heap-size[A] - 1
      MAX-HEAPIFY(A, 1)


Java实现

public void heapSort(int[] a)
{
int heapSize = a.length;
buildMaxHeap(a);
for (int i = a.length - 1; i > 0; i--)
{
swap(a, 0, i);
maxHeapify(a, 0, --heapSize);
}
}

private void buildMaxHeap(int[] a)
{
for (int i = a.length / 2; i >= 0; i--)
{
maxHeapify(a, i, a.length);
}
}

private void maxHeapify(int[] a, int i, int heapSize)
{
int largest = 0;
int l = 2 * i + 1;
int r = 2 * i + 2;
if (l < heapSize && a[l] > a[i])
{
largest = l;
}
else
{
largest = i;
}
if (r < heapSize && a[r] > a[largest])
{
largest = r;
}
if (largest != i)
{
swap(a, i, largest);
maxHeapify(a, largest, heapSize);
}
}

private void swap(int[] data, int src, int des)
{
int tmp = data[des];
data[des] = data[src];
data[src] = tmp;
}


用Java实现伪码需要注意

1.数组的下标:

大于1还是大于0,等等

因为Java的数组下标是从0开始,与伪码对应的结点 i 左孩子右孩子的下标分别是2*1+1, 2*i+2.

2.maxHeapify需要一参数heapSize是因为在heapSort交换后,要从堆中去掉此元素结点(此时去掉的元素结点就是堆中的最大结点)

3.堆排序是分3个过程来完成,在最后验证堆排序的实现是否正确,先测试验证maxHeapify正确,然后是建堆buildMaxHeap正确,最后验证

堆排序是否正确。否则一开始就验证堆排序,出了问题就不知道到底是哪个过程出错。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: