Java排序算法9:堆排序

来源:互联网 发布:io域名怎么注册 编辑:程序博客网 时间:2024/05/21 11:00

一.思想:

先将初始序列构造成一个大根堆(或者小根堆),此堆为初始无序区。再将最大记录R[1]与无序区的最后一个记录R[n]交换,由此可以得到新的无序区R[1....n-1]和有序区R[n]。由于交换之后新的根R[1]可能不满足大根堆的性质,故将当前无序区R[1...n-1]再次调整为堆,然后再次将R[1]与R[n-1]交换,依次类推。

二.图解:

给定一个整形数组num[]={16,7,3,20,17,8},对其进行堆排序。首先根据该数组元素构建一个完全二叉树,得到

然后需要构造初始堆,则从最后一个非叶节点开始调整,调整过程如下:

这样就得到了初始堆。

即每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)。有了初始堆之后就可以进行排序了。
此时3位于堆顶不满堆的性质,则需调整继续调整

这样整个区间便已经有序了。


三.实现代码:

    public class HeapSort {                public static void main(String[] args) {              int[] data5 = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };              print(data5);              heapSort(data5);              System.out.println("排序后的数组:");              print(data5);          }                public static void swap(int[] data, int i, int j) {              if (i == j) {                  return;              }              data[i] = data[i] + data[j];              data[j] = data[i] - data[j];              data[i] = data[i] - data[j];          }                public static void heapSort(int[] data) {              for (int i = 0; i < data.length; i++) {                  createMaxdHeap(data, data.length - 1 - i);                  swap(data, 0, data.length - 1 - i);              }          }                public static void createMaxdHeap(int[] data, int lastIndex) {              for (int i = (lastIndex - 1) / 2; i >= 0; i--) {                  // 保存当前正在判断的节点                  int k = i;                  // 若当前节点的子节点存在                  while (2 * k + 1 <= lastIndex) {                      // biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点                      int biggerIndex = 2 * k + 1;                      if (biggerIndex < lastIndex) {                          // 若右子节点存在,否则此时biggerIndex应该等于 lastIndex                          if (data[biggerIndex] < data[biggerIndex + 1]) {                              // 若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的值                              biggerIndex++;                          }                      }                      if (data[k] < data[biggerIndex]) {                          // 若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k                          swap(data, k, biggerIndex);                          k = biggerIndex;                      } else {                          break;                      }                  }              }          }                public static void print(int[] data) {              for (int i = 0; i < data.length; i++) {                  System.out.print(data[i] + "\t");              }              System.out.println();          }            }  

四.复杂度和应用:

时间复杂度:O(nlog2n)  空间复杂度:O(1)。  是不稳定的算法。

应用:也适用于海量的数据。


五.参考资料:

1.百度百科-堆排序:http://baike.baidu.com/view/157305.htm?fr=wordsearch

2.追竹的博客:http://blog.csdn.net/apei830/article/details/6584645

3.海子的博客园:http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html

六:相关排序代码下载:
包含(冒泡排序,桶排序,堆排序,插入排序,归并排序,快速排序,基数排序,选择排序,希尔排序)
免积分下载地址:http://download.csdn.net/detail/u014077165/7185895

0 0