首页 > 代码库 > 算法 Heap sort

算法 Heap sort

  1. // --------------------------------------------------------------------------------------------------------------------  
  2. // <copyright file="Program.cs" company="Chimomo‘s Company">  
  3. //  
  4. // Respect the work.  
  5. //  
  6. // </copyright>  
  7. // <summary>  
  8. //  
  9. // Heap sort.  
  10. //  
  11. // 堆排序是一种选择排序。时间复杂度为O(nlog<sub>2</sub>n)。  
  12. // 堆排序的特点是:在排序过程中,将待排序数组看成是一棵全然二叉树的顺序存储结构。利用全然二叉树中父结点和子结点之间的内在关系,在当前无序区中选择keyword最大(或最小)的记录。  
  13. //  
  14. // 基本思想  
  15. // 1.将待排序数组调整为一个大根堆。大根堆的堆顶元素就是这个堆中最大的元素。  
  16. // 2.将大根堆的堆顶元素和无序区最后一个元素交换,并将无序区最后一个位置列入有序区。然后将新的无序区调整为大根堆。

      

  17. // 3.反复操作。直到无序区消失为止。  
  18. // 初始时,整个数组为无序区。

    每一次交换,都是将大根堆的堆顶元素换入有序区,以保证有序区是有序的。

      

  19. //  
  20. // </summary>  
  21. // --------------------------------------------------------------------------------------------------------------------  
  22.   
  23. namespace CSharpLearning  
  24. {  
  25.     using System;  
  26.   
  27.     /// <summary>  
  28.     /// The program.  
  29.     /// </summary>  
  30.     public static class Program  
  31.     {  
  32.         /// <summary>  
  33.         /// 程序入口点。  
  34.         /// </summary>  
  35.         public static void Main()  
  36.         {  
  37.             int[] a = { 1, 14, 6, 2, 8, 66, 9, 3, 0, 10, 5, 34, 76, 809, 4, 7 };  
  38.             Console.WriteLine("Before Heap Sort...");  
  39.             foreach (int i in a)  
  40.             {  
  41.                 Console.Write(i + " ");  
  42.             }  
  43.   
  44.             Console.WriteLine("\r\n--------------------");  
  45.             Console.WriteLine("In Heap Sort...");  
  46.             HeapSort(a);  
  47.             Console.WriteLine("--------------------");  
  48.             Console.WriteLine("After Heap Sort...");  
  49.             foreach (int i in a)  
  50.             {  
  51.                 Console.Write(i + " ");  
  52.             }  
  53.   
  54.             Console.WriteLine(string.Empty);  
  55.         }  
  56.   
  57.         /// <summary>  
  58.         /// 堆排序方法。

      

  59.         /// </summary>  
  60.         /// <param name="a">  
  61.         /// 待排序数组。

      

  62.         /// </param>  
  63.         private static void HeapSort(int[] a)  
  64.         {  
  65.             BuildMaxHeap(a); // 建立大根堆。

      

  66.             Console.WriteLine("Build max heap:");  
  67.             foreach (int i in a)  
  68.             {  
  69.                 Console.Write(i + " "); // 打印大根堆。  
  70.             }  
  71.   
  72.             Console.WriteLine("\r\nMax heap in each iteration:");  
  73.             for (int i = a.Length - 1; i > 0; i--)  
  74.             {  
  75.                 Swap(ref a[0], ref a[i]); // 将堆顶元素和无序区的最后一个元素交换。  
  76.                 MaxHeaping(a, 0, i); // 将新的无序区调整为大根堆。

      

  77.   
  78.                 // 打印每一次堆排序迭代后的大根堆。  
  79.                 for (int j = 0; j < i; j++)  
  80.                 {  
  81.                     Console.Write(a[j] + " ");  
  82.                 }  
  83.   
  84.                 Console.WriteLine(string.Empty);  
  85.             }  
  86.         }  
  87.   
  88.         /// <summary>  
  89.         /// 由底向上建堆。由全然二叉树的性质可知,叶子结点是从index=a.Length/2開始。所以从index=(a.Length/2)-1结点開始由底向上进行大根堆的调整。  
  90.         /// </summary>  
  91.         /// <param name="a">  
  92.         /// 待排序数组。  
  93.         /// </param>  
  94.         private static void BuildMaxHeap(int[] a)  
  95.         {  
  96.             for (int i = (a.Length / 2) - 1; i >= 0; i--)  
  97.             {  
  98.                 MaxHeaping(a, i, a.Length);  
  99.             }  
  100.         }  
  101.   
  102.         /// <summary>  
  103.         /// 将指定的结点调整为堆。  
  104.         /// </summary>  
  105.         /// <param name="a">  
  106.         /// 待排序数组。  
  107.         /// </param>  
  108.         /// <param name="i">  
  109.         /// 须要调整的结点。  
  110.         /// </param>  
  111.         /// <param name="heapSize">  
  112.         /// 堆的大小,也指数组中无序区的长度。

      

  113.         /// </param>  
  114.         private static void MaxHeaping(int[] a, int i, int heapSize)  
  115.         {  
  116.             int left = (2 * i) + 1; // 左子结点。  
  117.             int right = 2 * (i + 1); // 右子结点。

      

  118.             int large = i; // 暂时变量。存放大的结点值。  
  119.   
  120.             // 比較左子结点。  
  121.             if (left < heapSize && a[left] > a[large])  
  122.             {  
  123.                 large = left;  
  124.             }  
  125.   
  126.             // 比較右子结点。  
  127.             if (right < heapSize && a[right] > a[large])  
  128.             {  
  129.                 large = right;  
  130.             }  
  131.   
  132.             // 如有子结点大于自身就交换。使大的元素上移;而且把该大的元素调整为堆以保证堆的性质。

      

  133.             if (i != large)  
  134.             {  
  135.                 Swap(ref a[i], ref a[large]);  
  136.                 MaxHeaping(a, large, heapSize);  
  137.             }  
  138.         }  
  139.   
  140.         /// <summary>  
  141.         /// 交换两个整数的值。  
  142.         /// </summary>  
  143.         /// <param name="a">整数a。</param>  
  144.         /// <param name="b">整数b。

    </param>  

  145.         private static void Swap(ref int a, ref int b)  
  146.         {  
  147.             int tmp = a;  
  148.             a = b;  
  149.             b = tmp;  
  150.         }  
  151.     }  
  152. }  
  153.   
  154. // Output:  
  155. /* 
  156. Before Heap Sort... 
  157. 1 14 6 2 8 66 9 3 0 10 5 34 76 809 4 7 
  158. -------------------- 
  159. In Heap Sort... 
  160. Build max heap: 
  161. 809 14 76 7 10 66 9 3 0 8 5 34 1 6 4 2 
  162. Max heap in each iteration: 
  163. 76 14 66 7 10 34 9 3 0 8 5 2 1 6 4 
  164. 66 14 34 7 10 4 9 3 0 8 5 2 1 6 
  165. 34 14 9 7 10 4 6 3 0 8 5 2 1 
  166. 14 10 9 7 8 4 6 3 0 1 5 2 
  167. 10 8 9 7 5 4 6 3 0 1 2 
  168. 9 8 6 7 5 4 2 3 0 1 
  169. 8 7 6 3 5 4 2 1 0 
  170. 7 5 6 3 0 4 2 1 
  171. 6 5 4 3 0 1 2 
  172. 5 3 4 2 0 1 
  173. 4 3 1 2 0 
  174. 3 2 1 0 
  175. 2 0 1 
  176. 1 0 
  177. 0 
  178. -------------------- 
  179. After Heap Sort... 
  180. 0 1 2 3 4 5 6 7 8 9 10 14 34 66 76 809 
  181. */  

算法 Heap sort