您的位置:首页 > 其它

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

2016-11-21 17:23 197 查看
  在《算法导论》的第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

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
的值,并且heap_size每次减少1,用MAX_HEAPIFY保持最大堆的特性,就能得到最终的答案。这个过程用伪代码表示为:
for n : length(A)-1 to 1
A
<-> 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);
}


  代码参考《算法导论》的伪代码思路,并未参考其他人实现过程,可能其中有些被笔者忽视的逻辑错误,还望指出批评。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 算法导论