日常记录:《算法导论》学习笔记之三—堆排序

  在《算法导论》的第6章,提到了堆排序(heapsort),该算法结合了select sort和insert sort算法的优点,利用二叉堆数据结构实现,这种数据结构类似于完全二叉树。每个结点的父节点和子节点都可以根据结点的下标计算该结点存放元素在数组中的下标。这里谈谈笔者对用到的数据结构的理解,我们利用的二叉堆数据结构并没有实际的建立这样的结构数据,而是在数组的基础上抽象出来的,对每个结点的操作,其实就是对原数组的操作,书中对结点的下标和数组的下标没有区分,而且默认数组的一个元素下标为1,而不是我们平常的0,所以在这篇学习笔记中,笔者按自己的理解更改一些内容,如果所修改部分有错误,还望可以批评指出。

  将数组的下标用字母n表示,结点的下标用字母i表示。结点与数组的下标对应关系如下:

对于下标为 i 的结点,其在数组中的下标:n =  i - 1;
左子树对应的数组下标: n = 2 * i - 1;
右子树对应的数组下标: n = 2 * i;
父结点对应的数组的下标: n = i / 2;
  我们要得到从下到大的序列,采用最大堆结构,即结点的元素值最大,其特点是A[ i / 2 ] > A[ i - 1 ],父结点的数值永远比子结点的数值大,通过MAX_HEAPIFY来保证堆者一特性,其伪代码如下:

l = LEFT(i)
r = RIGHT(i)
n = i - 1
largest = n
if  A[l] > A[n]
  largest = l
if r <= heap_size(A) and A[r] > A[largest]
  largest = r
if largest != n
  A[i] <-> A[largest]
  if (largest < heapsize(A) / 2
    MAX_HEAPIFY(A, largest + 1)
  根结点是最大的元素值,所以我们自底向上用MAX_HEAPIFY将数组变为一个最大堆,过程BUILD_MAX_HEAP每次循环都在i结点调用MAX_HEAPIFY,其伪代码如下:

heap_size(A) = length(A)
for i : length/2 to 1
  MAX_HEAPIFY(A, i)
  由最大堆的特点,根结点是数组中元素最大的值,我们只要将根结点依次从数组最后一位往前存放,即交换A[0]和A[n]的值,并且heap_size每次减少1,用MAX_HEAPIFY保持最大堆的特性,就能得到最终的答案。这个过程用伪代码表示为:

for n : length(A)-1 to 1
  A[n] <-> A[0]
  heap_size(A)--
  if (i != 1)
    MAX_HEAPIFY(A, 1)
  给定实例用C++实现heapsort如下:

#include 
   
   
    
    

int LEFT(int i);
int RIGHT(int i);
void MAX_HEAPIFY(int A[], int i, int lengthA);
void BUILD_MAX_HEAP(int A[], int lengthA);

int main(void)
{
    int length = 10;
    int heap_size = 10;
    int A[length] = {4, 1, 3, 2, 16, 9, 10, 14, 8 ,7};
    int temp;

    BUILD_MAX_HEAP(A, heap_size);
    for (int i = length - 1; i > 0; i--)
    {
        temp = A[i];
        A[i] = A[0];
        A[0] = temp;
        if (i > 1)
            MAX_HEAPIFY(A, 1, --heap_size);
    }

    for (int i = 0; i < length; i++)
        std::cout << A[i] << " ";

    return 0;
}

int LEFT(int i)
{
    return 2 * i - 1;
}

int RIGHT(int i)
{
    return 2 * i;
}

void MAX_HEAPIFY(int A[], int i, int lengthA)
{
    int temp = 0;
    int l = LEFT(i);
    int r = RIGHT(i);
    i--;
    int largest = i;
    if (A[l] > A[largest])
        largest = l;
    if (r < lengthA && A[r] > A[largest])
        largest = r;
    if (largest != i)
    {
        temp = A[i];
        A[i] = A[largest];
        A[largest] = temp;
        if (largest < lengthA / 2)
            MAX_HEAPIFY(A, largest + 1, lengthA);
    }
}

void BUILD_MAX_HEAP(int A[], int lengthA)
{
    int i = lengthA / 2;
    for ( ; i > 0; i--)
        MAX_HEAPIFY(A, i, lengthA);
}
   
   

  代码参考《算法导论》的伪代码思路,并未参考其他人实现过程,可能其中有些被笔者忽视的逻辑错误,还望指出批评。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值