堆排序

来源:互联网 发布:linux mint 18安装 编辑:程序博客网 时间:2024/05/16 03:04

堆排序

前言

    堆排序和归并排序一样,时间复杂度都是O(nlg(n)),和插入排序相同的是具有空间的原址性:任何时候都只需要常数个额外的空间元素存储临时数据。因此堆排序可以说是结合了之前讨论的两种排序算法的优点。

    (二叉)堆又是一个数组,它可以被堪称一个近似的完全二叉树,树上的每一个节点都对应着数组中的一个元素。从图中可以看到,除了叶节点之外,该树是完全充满的,而且是从左向右的填充。很容易就能够通过一个节点得到其父节点,左孩子和右孩子。
堆

    再利用数学归纳法稍加证明,则能够得到下面的结论:对于一个堆a[n]来说,从a[n/2]到a[n]均为叶节点,a[0]到a[n/2-1]的都为根节点

堆排序原理

    最大堆是用来实现堆排序的先决条件,最大堆的概念:在最大堆中,一个节点的值小于等于其父节点的值。,最小堆的概念则正好相反,这里不再赘述。
那么这个最大堆最上面的一个根节点即整个数组最大的节点,利用这一特性即可进行排序,将最大的那个节点和位于堆最后的一个节点值交换,整个数组最大的数就移动到了堆的最后。

    在交换了之后会出现最大堆被破坏的问题,因此每次提取最大值后需要对其a[0~n-1]子堆进行维护,即最大堆维护。提取一次,维护一次,直到子堆缩小成一个元素,这时整个堆呈升序排列。

    最大堆维护:维护最大堆即针对某一结点来对堆进行调整,使堆呈现最大堆的特性。对于一个节点i,假设其左孩子为left(i),右孩子为right(i),则需要找出a[i],a[left(i)],a[right(i)]中最大值的下标,并记录这个下标为max_index,如果max_index==i,则以i为根节点的树呈最大堆状态,不必理会,否则就将a[max_index]与a[i]交换,再以max_index作为根节点,一直递归查找下去,将下面的子树都调整为最大堆状态。
最大堆维护

C语言的实现

//针对节点i进行最大堆的调整void max_heapify(int* a, int i, int count){    int left_index , right_index ;    int max_index = i;    left_index = 2 * i + 1;    right_index = left_index + 1;    if ((left_index <= count) && (a[left_index] > a[max_index]))    max_index = left_index;    if ((right_index <= count) && (a[right_index] > a[max_index]))        max_index = right_index;    if (max_index != i)    {        int t = a[i];        a[i] = a[max_index];        a[max_index] = t;        max_heapify(a, max_index, count);    }}//建立最大堆void build_max_heap(int* a, int count){for (int i = count / 2; i >= 0; i--)    {        //对每个子根节点进行堆调整        max_heapify(a, i, count);    }}//开始堆排序void heap_sort(int* a, int count){    int t;    for (int i = count; i >= 1; i--)    {        t = a[0];        a[0] = a[i];        a[i] = t;        max_heapify(a, 0, i - 1);    }}void main(){    int count, *p;    printf("请输入需要排序的数的个数 :");    scanf_s("%d", &count);    p = (int *)malloc(count * 2);    printf("\n请输入需要排序的%d个数字:",count);    for (int i = 0; i < count; i++)    {        scanf_s("%d", p+i);    }    //依据输入的一列数字,建出一个最大堆    build_max_heap(p, count - 1);    printf("建立最大堆后的数组:");    for (int i = 0; i < count; i++)    {        printf("%d ", p[i]);    }    printf("\n\n");    //开始堆排序    heap_sort(p, count - 1);    printf("堆排序后的数组:");    for (int i = 0; i < count; i++)    {        printf("%d ", p[i]);    }    printf("\n\n");    system("pause");}
0 0
原创粉丝点击