堆排序的过程:

堆排序正是利用小根堆(或大根堆)来选取当前无序区中关键字小(或最大)的记录实现排序的。我们不妨利用大根堆来排序。每一趟排序的基本操作是: 将当前无序区调整为一个大根堆 ,选取关键字最大的堆顶记录,将它和无序区中的最后一个记录交换。这样,正好和直接选择排序相反,有序区是在原记录区的尾部形成并逐步向前扩大到整个记录区。

 

 

完整源码:http://yuncode.net/code/c_503a2ccccb89623

 

 

 
  
  1.  
  2. 016  public class HeapSort {    
  3.  
  4. 017      
  5.  
  6. 018     /**    
  7.  
  8. 019      * 排序算法的实现,对数组中指定的元素进行排序    
  9.  
  10. 020      *     
  11.  
  12. 021      * @param array    
  13.  
  14. 022      *            待排序的数组    
  15.  
  16. 023      * @param from    
  17.  
  18. 024      *            从哪里开始排序    
  19.  
  20. 025      * @param end    
  21.  
  22. 026      *            排到哪里    
  23.  
  24. 027      * @param c    
  25.  
  26. 028      *            比较器    
  27.  
  28. 029      */   
  29.  
  30. 030     public void sort(Integer[] array, int from, int end) {    
  31.  
  32. 031         // 创建初始堆    
  33.  
  34. 032         initialHeap(array, from, end);    
  35.  
  36. 033      
  37.  
  38. 034         /*    
  39.  
  40. 035          * 对初始堆进行循环,且从最后一个节点开始,直接树只有两个节点止 每轮循环后丢弃最后一个叶子节点,再看作一个新的树    
  41.  
  42. 036          */   
  43.  
  44. 037         for (int i = end - from + 1; i >= 2; i--) {    
  45.  
  46. 038             // 根节点与最后一个叶子节点交换位置,即数组中的第一个元素与最后一个元素互换    
  47.  
  48. 039             swap(array, from, i - 1);    
  49.  
  50. 040             // 交换后需要重新调整堆    
  51.  
  52. 041             adjustNote(array, 1, i - 1);    
  53.  
  54. 042         }    
  55.  
  56. 043      
  57.  
  58. 044     }    
  59.  
  60. 045      
  61.  
  62. 046     /**    
  63.  
  64. 047      * 初始化堆 比如原序列为:7,2,4,3,12,1,9,6,8,5,10,11 则初始堆为:1,2,4,3,5,7,9,6,8,12,10,11    
  65.  
  66. 048      *     
  67.  
  68. 049      * @param arr    
  69.  
  70. 050      *            排序数组    
  71.  
  72. 051      * @param from    
  73.  
  74. 052      *            从哪    
  75.  
  76. 053      * @param end    
  77.  
  78. 054      *            到哪    
  79.  
  80. 055      * @param c    
  81.  
  82. 056      *            比较器    
  83.  
  84. 057      */   
  85.  
  86. 058     private void initialHeap(Integer[] arr, int from, int end) {    
  87.  
  88. 059         int lastBranchIndex = (end - from + 1) / 2;// 最后一个非叶子节点    
  89.  
  90. 060         // 对所有的非叶子节点进行循环 ,且从最一个非叶子节点开始    
  91.  
  92. 061         for (int i = lastBranchIndex; i >= 1; i--) {    
  93.  
  94. 062             adjustNote(arr, i, end - from + 1);    
  95.  
  96. 063         }    
  97.  
  98. 064     }    
  99.  
  100. 065      
  101.  
  102. 066     /**    
  103.  
  104. 067      * 调整节点顺序,从父、左右子节点三个节点中选择一个最大节点与父节点转换    
  105.  
  106. 068      *     
  107.  
  108. 069      * @param arr    
  109.  
  110. 070      *            待排序数组    
  111.  
  112. 071      * @param parentNodeIndex    
  113.  
  114. 072      *            要调整的节点,与它的子节点一起进行调整    
  115.  
  116. 073      * @param len    
  117.  
  118. 074      *            树的节点数    
  119.  
  120. 075      * @param c    
  121.  
  122. 076      *            比较器    
  123.  
  124. 077      */   
  125.  
  126. 078     private void adjustNote(Integer[] arr, int parentNodeIndex, int len) {    
  127.  
  128. 079         int minNodeIndex = parentNodeIndex;    
  129.  
  130. 080         // 如果有左子树,i * 2为左子节点索引    
  131.  
  132. 081         if (parentNodeIndex * 2 <= len) {    
  133.  
  134. 082             // 如果父节点小于左子树时    
  135.  
  136. 083             if ((arr[parentNodeIndex - 1]    
  137.  
  138. 084                     .compareTo(arr[parentNodeIndex * 2 - 1])) < 0) {    
  139.  
  140. 085                 minNodeIndex = parentNodeIndex * 2;// 记录最大索引为左子节点索引    
  141.  
  142. 086             }    
  143.  
  144. 087      
  145.  
  146. 088             // 只有在有或子树的前提下才可能有右子树,再进一步断判是否有右子树    
  147.  
  148. 089             if (parentNodeIndex * 2 + 1 <= len) {    
  149.  
  150. 090                 // 如果右子树比最大节点更大    
  151.  
  152. 091                 if ((arr[minNodeIndex - 1]    
  153.  
  154. 092                         .compareTo(arr[(parentNodeIndex * 2 + 1) - 1])) < 0) {    
  155.  
  156. 093                     minNodeIndex = parentNodeIndex * 2 + 1;// 记录最大索引为右子节点索引    
  157.  
  158. 094                 }    
  159.  
  160. 095             }    
  161.  
  162. 096         }    
  163.  
  164. 097      
  165.  
  166. 098         // 如果在父节点、左、右子节点三都中,最大节点不是父节点时需交换,把最大的与父节点交换,创建大顶堆    
  167.  
  168. 099         if (minNodeIndex != parentNodeIndex) {    
  169.  
  170. 100             swap(arr, parentNodeIndex - 1, minNodeIndex - 1);    
  171.  
  172. 101             // 交换后可能需要重建堆,原父节点可能需要继续下沉    
  173.  
  174. 102             if (minNodeIndex * 2 <= len) {// 是否有子节点,注,只需判断是否有左子树即可知道    
  175.  
  176. 103                 adjustNote(arr, minNodeIndex, len);    
  177.  
  178. 104             }    
  179.  
  180. 105         }    
  181.  
  182. 106     }    
  183.  
  184. 107      
  185.  
  186. 108     /**    
  187.  
  188. 109      * 交换数组中的两个元素的位置    
  189.  
  190. 110      *     
  191.  
  192. 111      * @param array    
  193.  
  194. 112      *            待交换的数组    
  195.  
  196. 113      * @param i    
  197.  
  198. 114      *            第一个元素    
  199.  
  200. 115      * @param j    
  201.  
  202. 116      *            第二个元素    
  203.  
  204. 117      */   
  205.  
  206. 118     public void swap(Integer[] array, int i, int j) {    
  207.  
  208. 119         if (i != j) {// 只有不是同一位置时才需交换    
  209.  
  210. 120             Integer tmp = array[i];    
  211.  
  212. 121             array[i] = array[j];    
  213.  
  214. 122             array[j] = tmp;    
  215.  
  216. 123         }    
  217.  
  218. 124     }    
  219.  
  220. 125      
  221.  
  222. 126     /**    
  223.  
  224. 127      * 测试    
  225.  
  226. 128      *     
  227.  
  228. 129      * @param args    
  229.  
  230. 130      */   
  231.  
  232. 131     public static void main(String[] args) {    
  233.  
  234. 132         Integer[] intgArr = { 59142638070, -7, -134 };    
  235.  
  236. 133         HeapSort heapsort = new HeapSort();    
  237.  
  238. 134         heapsort.sort(intgArr, 0, intgArr.length - 1);    
  239.  
  240. 135         for (Integer intObj : intgArr) {    
  241.  
  242. 136             System.out.print(intObj + " ");    
  243.  
  244. 137         }    
  245.  
  246. 138     }    
  247.  
  248. 139      
  249.  
  250. 140 }