C# 实现堆排序的算法
2008-09-25 10:34
281 查看
堆排序是一树形选择排序,在排序过程中,将R[1..N]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。
堆的定义:
N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性:Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2])。
堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均大于等于其孩子结点的关键字。例如序列10,15,56,25,30,70就是一个 堆,它对应的完全二叉树如上图所示。这种堆中根结点(称为堆顶)的关键字最小,我们把它称为小根堆。反之,若完全二叉树中任一非叶子结点的关键字均大于等 于其孩子的关键字,则称之为大根堆。
排序过程:
堆排序正是利用小根堆(或大根堆)来选取当前无序区中 关键字小(或最大)的记录实现排序的。我们不妨利用大根堆来排序。每一趟排序的基本操作是:将当前无序区调整为一个大根堆,选取关键字最大的堆顶记录,将 它和无序区中的最后一个记录交换。这样,正好和直接选择排序相反,有序区是在原记录区的尾部形成并逐步向前扩大到整个记录区。
【示例】:对关键字序列42,13,91,23,24,16,05,88建堆。
程序实现
/// <summary>
/// 小根堆排序
/// </summary>
/// <param name="dblArray"></param>
/// <param name="StartIndex"></param>
/// <returns></returns>
private static void HeapSort(ref double[] dblArray )
{
for(int i = dblArray.Length -1 ; i >= 0; i--)
{
if(2*i+1<dblArray.Length)
{
int MinChildrenIndex = 2*i+1 ;
//比较左子树和右子树,记录最小值的Index
if(2*i+2 < dblArray.Length )
{
if(dblArray[2*i+1]>dblArray[2*i+2])
MinChildrenIndex = 2*i+2;
}
if(dblArray[i] > dblArray[MinChildrenIndex])
{
ExchageValue(ref dblArray[i],ref dblArray[MinChildrenIndex]);
NodeSort(ref dblArray ,MinChildrenIndex);
}
}
}
}
/// <summary>
/// 节点排序
/// </summary>
/// <param name="dblArray"></param>
/// <param name="StartIndex"></param>
private static void NodeSort(ref double[] dblArray,int StartIndex)
{
while(2*StartIndex+1 < dblArray.Length)
{
int MinChildrenIndex = 2*StartIndex+1 ;
if(2*StartIndex+2 < dblArray.Length )
{
if(dblArray[2*StartIndex+1]>dblArray[2*StartIndex+2])
{
MinChildrenIndex = 2*StartIndex+2;
}
}
if(dblArray[StartIndex] > dblArray[MinChildrenIndex])
{
ExchageValue(ref dblArray[StartIndex],ref dblArray[MinChildrenIndex]);
StartIndex = MinChildrenIndex ;
}
}
}
/// <summary>
/// 交换值
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>
private static void ExchageValue(ref double A , ref double B)
{
double Temp = A ;
A = B ;
B = Temp ;
}
堆的定义:
N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性:Ki≤K2i Ki ≤K2i+1(1≤ I≤ [N/2])。
排序过程:
堆排序正是利用小根堆(或大根堆)来选取当前无序区中 关键字小(或最大)的记录实现排序的。我们不妨利用大根堆来排序。每一趟排序的基本操作是:将当前无序区调整为一个大根堆,选取关键字最大的堆顶记录,将 它和无序区中的最后一个记录交换。这样,正好和直接选择排序相反,有序区是在原记录区的尾部形成并逐步向前扩大到整个记录区。
【示例】:对关键字序列42,13,91,23,24,16,05,88建堆。
/// <summary>
/// 小根堆排序
/// </summary>
/// <param name="dblArray"></param>
/// <param name="StartIndex"></param>
/// <returns></returns>
private static void HeapSort(ref double[] dblArray )
{
for(int i = dblArray.Length -1 ; i >= 0; i--)
{
if(2*i+1<dblArray.Length)
{
int MinChildrenIndex = 2*i+1 ;
//比较左子树和右子树,记录最小值的Index
if(2*i+2 < dblArray.Length )
{
if(dblArray[2*i+1]>dblArray[2*i+2])
MinChildrenIndex = 2*i+2;
}
if(dblArray[i] > dblArray[MinChildrenIndex])
{
ExchageValue(ref dblArray[i],ref dblArray[MinChildrenIndex]);
NodeSort(ref dblArray ,MinChildrenIndex);
}
}
}
}
/// <summary>
/// 节点排序
/// </summary>
/// <param name="dblArray"></param>
/// <param name="StartIndex"></param>
private static void NodeSort(ref double[] dblArray,int StartIndex)
{
while(2*StartIndex+1 < dblArray.Length)
{
int MinChildrenIndex = 2*StartIndex+1 ;
if(2*StartIndex+2 < dblArray.Length )
{
if(dblArray[2*StartIndex+1]>dblArray[2*StartIndex+2])
{
MinChildrenIndex = 2*StartIndex+2;
}
}
if(dblArray[StartIndex] > dblArray[MinChildrenIndex])
{
ExchageValue(ref dblArray[StartIndex],ref dblArray[MinChildrenIndex]);
StartIndex = MinChildrenIndex ;
}
}
}
/// <summary>
/// 交换值
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>
private static void ExchageValue(ref double A , ref double B)
{
double Temp = A ;
A = B ;
B = Temp ;
}
相关文章推荐
- C# 实现常用的算法-- 堆排序(转)
- 【算法导论】堆排序实现
- 关于算法—— 一维字符串数组之间组合问题的C#实现
- 18位身份证号验证算法的原理以及C#实现和在管理系统的应用
- 冒泡排序、选择排序、堆排序、快速排序、插入排序算法复杂度分析与算法实现(自己总结与转)
- C#实现的18位身份证格式验证算法
- 堆排序原理及算法实现(最大堆)
- 以下是关于对称加密算法的C#实现代码,大家可以根据需要更改不同的算法,文中以Rijndael算法为例
- 仿淘宝,拍拍等查询关键词字符串编码算法实现(C#版),抛弃URLENCODE!
- C#实现的18位身份证格式验证算法[转载] 选择自 mYang 的 Blog
- C#实现的18位身份证格式验证算法
- C#实现的18位身份证格式验证算法[转载] 选择自 mYang 的 Blog
- 数组实现堆排序(来源算法导论)
- 图像相似度算法的C#实现及测评
- C#实现的18位身份证格式验证算法
- C#实现的18位身份证格式验证算法
- 笔试题中的两道简单算法题(用C#实现)
- 堆排序(基本思想以及算法实现)
- c#实现猜数字算法,对所有CASE能在10步内求得其解
- LCS 最长公共子串算法实现 C#