堆排序
性质
- 结构近似完全二叉树 构建时 从上到下 从左到右
- 子节点的键值总是都大于(或小与)父节点键值
示例
-
假设排序对象为一维数组nums
-
其对应的完全二叉树[根左右构建二叉树]
-
节点与数组索引下标对应如下
- 最后一个子节点 -- lastIndex=nums.Length-1
- 最后一个子节点对应的父节点 parentIndex=(lastIndex-1)/2
- 每个父节点对应的左右子节点下标为 -- left=2 * parentIndex+1; right=2 * parentIndex+2;
通常处理顺序
- 根据数组构建堆
/// <summary>
/// 根据数组构建堆
/// </summary>
/// <param name="nums"></param>
public static void BuildHeapify(int[] nums)
{
//总节点个数
var n = nums.Length ;
var lastNodeIndex = n - 1;
//获取最后一个子节点对应的父节点下标
var parent = (lastNodeIndex - 1) / 2;
//从tree的最后一个节点进行heapify 依次向上heapify
for (int i = parent; i >=0; i--)
{
Heapify(nums,nums.Length,i);
}
}
/// <summary>
/// 构建堆 从根节点i 进行构建
/// </summary>
/// <param name="nums"></param>
/// <param name="n">堆的总节点数</param>
/// <param name="i">构建起点--根节点对应数组下标</param>
public static void Heapify(int[] nums, int n, int i)
{
if (i > n)
return;
var max = i;
//获取i的子节点C1下标
var c1 = 2 * i + 1;
//获取i的子节点C2下标
var c2 = 2 * i + 2;
//比较获取 根节点i i的子节点C1 i的子节点C2 三者中的最大值
if (c1 < n && nums[c1] > nums[max])
max = c1;
if (c2 < n && nums[c2] > nums[max])
max = c2;
if (max != i)
{
Swap(nums, i, max);
//再将交换的子节点 作为父节点 将其下的子节点进行heapify(迭代)
Heapify(nums, n, max);
}
}
- 构建堆后 将最大值与最后一个节点交换 再将除最大节点的剩余节点进行排序 最后所有的值都按从小到大进行排序了
public static void HeapifySort(int[] nums,int n)
{
BuildHeapify(nums);
for (int i = n-1; i >=0; i--)
{
//将最大值与最后一个节点交换 再将除最大节点的剩余节点进行排序
Swap(nums, 0, i);
Heapify(nums, i, 0);
}
}