堆排序

  1 package com.yan.algorithm;
  2 
  3 import java.util.Arrays;
  4 
  5 public class HeapSortTest {
  6     /*
  7      * 堆得规则:任何一个parent节点都比其左右子节点大(或者小)。
  8      * 堆排序步骤:
  9      * 1.初始化堆,即从倒数第一个parent节点开始往前,进行调整,使任何一个parent节点都比其左右子节点大(或者小)。
 10      * 2.堆初始化后的堆进行排序,每次将堆顶节点和堆最后一个节点进行交换,并调整,循环n次。
 11      * 三个方法:
 12      * (1)初始化 heapInit()
 13      *         从倒数第一个parent节点开始往前,进行调整
 14      * (2)调整 heapify()
 15      *         由parent节点找到其2个子节点,并交换使得parent节点为最大,递归调整交换的子树
 16      * (3)排序 sort()
 17      *         每次将堆顶节点和堆最后一个节点进行交换,并调整,循环n次
 18      */
 19 
 20     private static int[] data = new int[] { 12, 13, 14, 46, 15, 65, 99 };
 21 
 22     public HeapSortTest() {
 23     }
 24 
 25     public static void main(String[] args) {
 26 
 27         heapInit(data, data.length);
 28         sort(data);
 29         System.out.println(Arrays.toString(data));
 30     }
 31 
 32     /**
 33      * 创建初始堆,若堆排序目的是为了递增排序,则初始堆是一个最大堆。
 34      * 
 35      * @param data
 36      * @param length为数组长度
 37      */
 38     public static void heapInit(int[] data, int length) {
 39         // 从最后一个parent节点开始调整。
 40         int start = getParentIndex(length - 1);
 41         // 因为从倒数第一个parent节点开始往前的每一个节点都要调整,所以要用for循环。
 42         for (int i = start; i >= 0; i--) {
 43             heapify(data, length, i);
 44         }
 45     }
 46 
 47     /*
 48      * 在parent和左右子节点3者之间交换调整,使得parent是3者中最大值.
 49      * heapsize是需要调整的节点数的长度,用来判断子节点是否越界(和在sort方法中设置调整的范围,因为已排序的后面一部分不需要再调整了)。
 50      */
 51     public static void heapify(int[] data, int heapsize, int start) {
 52         int largest = start;
 53         int leftChild = getLeftChildIndex(start);
 54         int rightChild = getRightChildIndex(start);
 55         if (leftChild < heapsize && data[largest] < data[leftChild]) {
 56             largest = leftChild;
 57         }
 58         if (rightChild < heapsize && data[largest] < data[rightChild]) {
 59             largest = rightChild;
 60         }
 61         /*
 62          * 如果发生了交换,则该子节点的子树也不再符合堆的规则。 因此,需要继续对其子节点进行递归调整。
 63          */
 64         if (largest != start) {
 65             swap(data, start, largest);
 66             heapify(data, heapsize, largest);
 67         }
 68 
 69     }
 70 
 71     /**
 72      * 对初始化过的堆进行排序(将最大堆排序为递增堆 “即,每次将堆顶元素和堆末尾的元素进行交换,然后从堆顶元素开始进行调整”,
 73      * 或者将最小堆排序为递减堆。“即,同上”)
 74      * 
 75      * @param data
 76      */
 77     public static void sort(int[] data) {
 78         for (int i = data.length - 1; i > 0; i--) {
 79             swap(data, i, 0);
 80             heapify(data, i, 0);
 81         }
 82     }
 83 
 84     public static void swap(int[] data, int x, int y) {
 85         int temp = data[x];
 86         data[x] = data[y];
 87         data[y] = temp;
 88     }
 89 
 90     public static int getLeftChildIndex(int parent) {
 91         return (parent << 1) + 1;
 92     }
 93 
 94     public static int getRightChildIndex(int parent) {
 95         return (parent << 1) + 2;
 96     }
 97 
 98     public static int getParentIndex(int child) {
 99         return (child - 1) >> 1;
100     }
101 
102 }

 

posted on 2016-05-27 16:57  Yanspecial  阅读(196)  评论(0编辑  收藏  举报