堆排序的JAVA实现

堆排序

堆排序是另一种选择排序方法,它是树型选择排序的改进,它使用的辅助空间较少,仅需要一个元素用于空间交换。

堆:根结点的关键码值或者大于左右子树或者都小于左右子树,而且左右子树也是堆。

如果每个结点的值都大于左右子树关键码值,称之为大顶堆。每个结点的值都小于左右子树的关键码值,称之为小顶堆。

首先,堆是一个完全二叉树。堆排序包含两个过程:

(1)初建堆

(2)调整堆

 

调整堆:对于第二个过程,描述如下,第一次,取出堆顶元素与R[n]进行交换,然后从根结点开始调整堆,根结点与左右孩子中较大者交换,这样,左右子树的堆会被破坏,继续进行上述操作,直到叶子结点为止。第二次,取出堆顶元素与R[n-1]交换,然后调整堆。

初建堆:从非终端结点开始一直到根结点,执行调整堆的过程。这样,就会建立一个大顶堆。

 

如果排序过程中,是按照从小到大正序,那么建立一个大顶堆。如果是逆序就建立一个小顶堆。

 

 

堆排序算法的JAVA实现:

/**
 * 堆排序包括两个步骤 (1)初始堆(堆的定义:(1)堆是一个完全二叉树(2)根结点的值或者大于左右子树的值或者小于左右子树的值(3)左右子树也是一个堆)
 * (2)调整堆(当初始小顶堆之后,堆顶元素是最小的元素,取出最小的元素与最后一个元素相交换,再把剩下n-1个元素调整成堆,依次调整直到1为止)
 * 非终端节点调整 初始堆时从n/2向上调整成堆 把第一个元素与最后一个元素交换之后从第1个元素开始调整成新堆
 *
 * @author Administrator
 *
 */
public class HeapSort {
 public static void main(String[] args) {
  int num[] = new int[] { 0, 5, 40, 32, 2, 2221 };
  heapsort(num, 5);
  for (int x = 0; x < num.length - 1; x++) {
   System.out.print(num[x + 1] + " ");
  }
 }

//调整堆

 public static void adjustHeap(int[] num, int s, int t) {

  int i = s;
  int x = num[s];
  for (int j = 2 * i; j <= t; j = 2 * j) {
   if (j < t && num[j] < num[j + 1])
    j = j + 1;// 找出较大者把较大者给num[i]
   if (x > num[j])
    break;
   num[i] = num[j];
   i = j;

  }

  num[i] = x;

 }

 

 public static void heapsort(int[] num, int n) {
  // 初始建堆从n/2开始向根调整

  int i;
  for (i = n / 2; i >= 1; i--) {

   adjustHeap(num, i, n);//初始堆过程
  }

  for (i = n; i > 1; i--) {
   num[0] = num[i];// 将堆顶元素与第n,n-1,.....2个元素相交换
   num[i] = num[1];
   num[1] = num[0];// 从num[1]到num[i-1]调整成新堆
   adjustHeap(num, 1, i - 1);

  }

 }

}

 

性能分析:

时间复杂度:

堆是一个完全二叉树,设树高为k=log2n+1,从根到叶的调整,关键码比较的次数为2(k-1),交换的次数至多为k次。所以比较的次数不超过

2*(log2(n-1)+log2(n-2)+....+log22)<2nlog2n

而比较的次数不超过4n.所以堆排序的时间复杂度为O(nlogn).

空间复杂度:

需要一个单元的辅助空间用于交换,所以辅助空间为O(1).

稳定性:

堆排序调整过程中存在着交换,所以堆排序是一个不稳定的排序算法。

堆排序的实例过程可以参考http://blog.sina.com.cn/s/blog_534408920100acqv.html.

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值