您的位置:首页 > 其它

算法 Heap sort

2015-03-13 16:28 197 查看
// --------------------------------------------------------------------------------------------------------------------  

// <copyright file="Program.cs" company="Chimomo's Company">  

//  

// Respect the work.  

//  

// </copyright>  

// <summary>  

//  

// Heap sort.  

//  

// 堆排序是一种选择排序,时间复杂度为O(nlog<sub>2</sub>n)。  

// 堆排序的特点是:在排序过程中,将待排序数组看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中父结点和子结点之间的内在关系,在当前无序区中选择关键字最大(或最小)的记录。  

//  

// 基本思想  

// 1.将待排序数组调整为一个大根堆。大根堆的堆顶元素就是这个堆中最大的元素。  

// 2.将大根堆的堆顶元素和无序区最后一个元素交换,并将无序区最后一个位置列入有序区,然后将新的无序区调整为大根堆。  

// 3.重复操作,直到无序区消失为止。  

// 初始时,整个数组为无序区。每一次交换,都是将大根堆的堆顶元素换入有序区,以保证有序区是有序的。  

//  

// </summary>  

// --------------------------------------------------------------------------------------------------------------------  

  

namespace CSharpLearning  

{  

    using System;  

  

    /// <summary>  

    /// The program.  

    /// </summary>  

    public static class Program  

    {  

        /// <summary>  

        /// 程序入口点。  

        /// </summary>  

        public static void Main()  

        {  

            int[] a = { 1, 14, 6, 2, 8, 66, 9, 3, 0, 10, 5, 34, 76, 809, 4, 7 };  

            Console.WriteLine("Before Heap Sort...");  

            foreach (int i in a)  

            {  

                Console.Write(i + " ");  

            }  

  

            Console.WriteLine("\r\n--------------------");  

            Console.WriteLine("In Heap Sort...");  

            HeapSort(a);  

            Console.WriteLine("--------------------");  

            Console.WriteLine("After Heap Sort...");  

            foreach (int i in a)  

            {  

                Console.Write(i + " ");  

            }  

  

            Console.WriteLine(string.Empty);  

        }  

  

        /// <summary>  

        /// 堆排序方法。  

        /// </summary>  

        /// <param name="a">  

        /// 待排序数组。  

        /// </param>  

        private static void HeapSort(int[] a)  

        {  

            BuildMaxHeap(a); // 建立大根堆。  

            Console.WriteLine("Build max heap:");  

            foreach (int i in a)  

            {  

                Console.Write(i + " "); // 打印大根堆。  

            }  

  

            Console.WriteLine("\r\nMax heap in each iteration:");  

            for (int i = a.Length - 1; i > 0; i--)  

            {  

                Swap(ref a[0], ref a[i]); // 将堆顶元素和无序区的最后一个元素交换。  

                MaxHeaping(a, 0, i); // 将新的无序区调整为大根堆。  

  

                // 打印每一次堆排序迭代后的大根堆。  

                for (int j = 0; j < i; j++)  

                {  

                    Console.Write(a[j] + " ");  

                }  

  

                Console.WriteLine(string.Empty);  

            }  

        }  

  

        /// <summary>  

        /// 由底向上建堆。由完全二叉树的性质可知,叶子结点是从index=a.Length/2开始,所以从index=(a.Length/2)-1结点开始由底向上进行大根堆的调整。  

        /// </summary>  

        /// <param name="a">  

        /// 待排序数组。  

        /// </param>  

        private static void BuildMaxHeap(int[] a)  

        {  

            for (int i = (a.Length / 2) - 1; i >= 0; i--)  

            {  

                MaxHeaping(a, i, a.Length);  

            }  

        }  

  

        /// <summary>  

        /// 将指定的结点调整为堆。  

        /// </summary>  

        /// <param name="a">  

        /// 待排序数组。  

        /// </param>  

        /// <param name="i">  

        /// 需要调整的结点。  

        /// </param>  

        /// <param name="heapSize">  

        /// 堆的大小,也指数组中无序区的长度。  

        /// </param>  

        private static void MaxHeaping(int[] a, int i, int heapSize)  

        {  

            int left = (2 * i) + 1; // 左子结点。  

            int right = 2 * (i + 1); // 右子结点。  

            int large = i; // 临时变量,存放大的结点值。  

  

            // 比较左子结点。  

            if (left < heapSize && a[left] > a[large])  

            {  

                large = left;  

            }  

  

            // 比较右子结点。  

            if (right < heapSize && a[right] > a[large])  

            {  

                large = right;  

            }  

  

            // 如有子结点大于自身就交换,使大的元素上移;并且把该大的元素调整为堆以保证堆的性质。  

            if (i != large)  

            {  

                Swap(ref a[i], ref a[large]);  

                MaxHeaping(a, large, heapSize);  

            }  

        }  

  

        /// <summary>  

        /// 交换两个整数的值。  

        /// </summary>  

        /// <param name="a">整数a。</param>  

        /// <param name="b">整数b。</param>  

        private static void Swap(ref int a, ref int b)  

        {  

            int tmp = a;  

            a = b;  

            b = tmp;  

        }  

    }  

}  

  

// Output:  

/* 

Before Heap Sort... 

1 14 6 2 8 66 9 3 0 10 5 34 76 809 4 7 

-------------------- 

In Heap Sort... 

Build max heap: 

809 14 76 7 10 66 9 3 0 8 5 34 1 6 4 2 

Max heap in each iteration: 

76 14 66 7 10 34 9 3 0 8 5 2 1 6 4 

66 14 34 7 10 4 9 3 0 8 5 2 1 6 

34 14 9 7 10 4 6 3 0 8 5 2 1 

14 10 9 7 8 4 6 3 0 1 5 2 

10 8 9 7 5 4 6 3 0 1 2 

9 8 6 7 5 4 2 3 0 1 

8 7 6 3 5 4 2 1 0 

7 5 6 3 0 4 2 1 

6 5 4 3 0 1 2 

5 3 4 2 0 1 

4 3 1 2 0 

3 2 1 0 

2 0 1 

1 0 



-------------------- 

After Heap Sort... 

0 1 2 3 4 5 6 7 8 9 10 14 34 66 76 809 

*/  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: