算法 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
*/
// <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
*/
相关文章推荐
- HeapSort——堆排序实现(算法类)
- Atitit 算法之道 attilax著 1. 第二部分(Part II) 排序与顺序统计(Sorting and Order Statistics) 1 2. 第六章 堆排序(Heapsort)
- algorithm: heap sort in python 算法导论 堆排序
- 算法珠玑--再看堆排序(Heap Sort)的实现
- Java堆排序(HeapSort)算法实现
- 算法总结系列之一:堆排序(Heap Sort)
- 算法珠玑--再看堆排序(Heap Sort)的实现
- 堆排序(Heap Sort) 算法实现 C语言版
- 小小c#算法题 - 7 - 堆排序 (Heap Sort)
- 算法分析之——heap-sort堆排序
- 算法 Heap sort
- 算法总结系列之一:堆排序(Heap Sort)
- 自己动手写算法.Sort.HeapSort
- 堆排序(Heap Sort)算法学习
- 每天一个小算法(Heapsort)
- 自己动手写算法.Sort.HeapSort
- 每天一个小算法(Heapsort)
- 每天一个小算法(Heapsort)
- 算法学习笔记之——priority queue、heapsort、symbol table、binary search trees
- 算法学习 - 堆排序 ( HeapSort ) C++实现