您的位置:首页 > 其它

算法 Heap sort

2017-07-04 18:36 197 查看
// --------------------------------------------------------------------------------------------------------------------

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

//

// Respect the work.

//

// </copyright>

// <summary>

//

// Heap sort.

//

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

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

//

// 基本思想

// 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

0

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

After Heap Sort...

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

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