您的位置:首页 > 其它

堆排序

2016-03-17 17:11 211 查看

概述

堆,可以视为一颗完全二叉树,其节点之间满足父节点不小于(不大于)两个子节点的值,这样的堆被称为大(小)根堆。用数学符号表示为:

大根堆:A[parent(i)] >= A[i]

小根堆:A[parent(i)] <= A[i]

在堆排序中,需要能够快速的找到节点的父节点,及其左右孩子节点。例如数组A[0 … n],可以将下标与树的节点按照下图进行匹配。



通过上图的方式给树的节点与数组下标的建立对应关系,可以很容易的计算出节点的父节点、左孩子和右孩子节点的下标:

#define LEFT(i)     (((i) << 1) + 1)
#define RIGHT(i)    (((i) << 1) + 2)
#define PARENT(i)   (((i) - 1) >> 1)


若是数组下标从1开始对应树的根节点则有:

#define LEFT(i)     ((i) << 1)
#define RIGHT(i)    (((i) << 1) + 1)
#define PARENT(i)   ((i) >> 1)


堆排序的过程主要可以分为三个阶段:

建堆。建堆是利用堆化过程将一个大小为n的数组转换为最大(小)堆的过程。

堆化。堆化用于保持堆的特性,是堆排序中最为重要的过程。其思想是比较节点i和它左右孩子节点,并选择三者中最大(小)的元素。如果最大值不是节点i,则调换节点i与最大子节点的值,并递归的对子节点进行兑换过程。

排序。该操作是从堆中取出最大(小)元素,并通过堆化过程维持堆的特性。

堆排序的实现

#include <stdio.h>

/**< 查找左孩子节点下标 */
#define LEFT(i)     (((i) << 1) + 1)

/**< 查找右孩子节点下标 */
#define RIGHT(i)    (((i) << 1) + 2)

/**< 查找父节点下标 */
#define PARENT(i)   (((i) - 1) >> 1)

/* @brief 堆化,保持堆的性质
* @param A [in] 数组地址
* @param len [in] 数组元素个数
* @param i [in] 需要堆化的元素的下标
*/
static void
heapify(int *A, int len, int i)
{
int largest;
int l, r;

l = LEFT(i);
r = RIGHT(i);

largest = i;

if (l < len && A[l] > A[largest]) {
largest = l;
}

if (r < len && A[r] > A[largest]) {
largest = r;
}

if (largest != i) {
int tmp = A[i];
A[i] = A[largest];
A[largest] = tmp;
heapify(A, len, largest);  /* 递归的对孩子节点进行堆化操作 */
}
}

/* @brief 建立堆
* @param A [in] 数组地址
* @param len [in] 数组元素个数
*/
static void
build_heap(int *A, int len)
{
int i = PARENT(len - 1);

while (i >= 0) {
heapify(A, len, i);
i--;
}
}

/* @brief 堆排序
* @param A [in] 待排序数组地址
* @param len [in] 待排序数组元素个数
*/
void hsort(int *A, int len)
{
int tmp;

build_heap(A, len);
len--;
while (len > 0) {
tmp = A[0];
A[0] = A[len];
A[len] = tmp;
heapify
b379
(A, len, 0);
len--;
}
}

void display(int *A, int len)
{
int i;

for (i = 0; i < len; i++) {
printf("%d ", A[i]);
}
printf("\n");
}

int main()
{
int A[] = {10, 32, 43, 31, 2, 45, 12, 9, 71, 41};
int len = sizeof(A) / sizeof(A[0]);

display(A, len);

hsort(A, len);

display(A, len);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: