堆排序的个人理解
首先呢,希望学习堆排序的各位千万不要以为这个算法有多么的难,可以理解为“构造树”。
堆排序的过程就是构造树的过程。
这里先指明三个公式:
假设当前节点下标为i,则
- 父节点的下标(i - 1) / 2
- 左右叶子节点的下标分别是2 * i +1、2 * i + 2
排序的过程:
假设待排序数组为int a[10];
1. 遍历所有非叶子的节点,建立大根堆/小根堆的完全二叉树
2. 将树的根节点(a[0])与最后的子节点(a[9])交换位置
3. 把前面的9个元素重新建立树
4. 将树的根节点(a[0])与最后的子节点(a[8])交换位置
5. 把前面的8个元素重新建立树
6. …
7. 直到交换完毕
这么说不知道多少人能理解………..本人不太会画图,提供一篇文章,我觉得里面的图很容易理解
http://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html
下面是代码实现,注释已经很清楚了
/// 堆排序-整理堆
void BuildHeap(int a[], int index, int size)
{
// 初始化待比较的值
int value = a[index];
// 判断叶子是否存在
while (2 * index + 1 < size)
{
// 取出左叶子节点的下标
int i = 2 * index + 1;
// 比较左右两个叶子的大小(没越界的情况下)
if (i + 1 < size && a[i] < a[i + 1])
{
i++;
}
// 待比较的父节点比叶子大则跳出
if (value > a[i])
{
break;
}
// 父和叶子交换位置
swap(a[index], a[i]);
// 重排叶子
index = i;
}
}
/// 堆排序
void HeapSort(int a[], int size)
{
// 建立大根堆
// 最后的非叶子节点的下标为size/2
for (int i = size / 2; i >= 0; i--)
{
// 构建树
BuildHeap(a, i, size);
}
// 头尾交换,最值放到最后面的有序区,然后对其它无序区重构树
for (int i = size - 1; i >= 0; i--)
{
// 头尾交换
swap(a[0], a[i]);
// 重新构建i - 1的元素树
BuildHeap(a, 0, i - 1);
}
}
void main()
{
int a[] = {10,9,8,7,6,5,4,3,2,1};
HeapSort(a, sizeof(a) / sizeof(a[0]));
}
markdown编辑器连颜色都不能变啊。。。