数据结构与算法分析(c语言)--堆排序分析

1、什么是堆

堆排序是利用堆的性质进行的一种选择排序。下面先讨论一下堆。
堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:
Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]
或者
Key[i]>=Key[2i+1]&&key>=key[2i+2]
即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。
堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。

2、堆排序过程

利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。
其基本思想为(大顶堆):
1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

操作过程如下:
1)初始化堆:将R[1..n]构造为堆;
2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。

因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。

3、初始堆建立

数据结构与算法分析(c语言)--堆排序分析_第1张图片
初始堆建立

4、建堆时间复杂度分析

建立初始堆的时间复杂度是O(n),之前有同学面百度数据挖掘岗位的时候有闻到这个问题,所以在此记录一下:
原文:http://blog.csdn.net/hupenghui1224/article/details/57427045
堆是一颗完全二叉树,假设有n个节点,树高这里写图片描述

证明方法如下:

  1. 假设根节点的高度为0,叶子节点高度为h,那么每层包含的元素个数为2^x,x从0到h。
  2. 构建堆的过程是自下而上,对于每层非叶子节点需要调整的次数为h-x,因此很明显根节点需要调整(h-0)次,第一层节点需要调整(h-1)次,最下层非叶子节点需要调整1次。
  3. 因此可知,构造树高为h的二叉堆精确时间复杂度为:
    s = 12^(h-1) + 22(h-2)+……+h*20

可以看出以上公式是等差数列和等比数列乘积之和,可以通过错位相减求:
2s = 2^h + 22^(h-1)+32(h-2)+……+h*21

因此可得:
s = 2s -s = 2^h + 2^(h-1) + 2^(h-2) +…… + 2^1 - h

最终可以通过等比数列公式进行计算得到s = 2*2^h - 2 -h
将这里写图片描述代入的s = 2n - 2 - log2(n),近似的时间复杂度就是O(n)。

5、堆排序过程

堆排序过程

6、完整代码

#include 
#include 

void percDown(int list[],int i,int N)
{
    int tmp;
    int child;
    for (tmp = list[i];(2*i + 1) list[child])
            child ++;
        if (tmp < list[child])
            list[i] = list[child];
        else
            break;
    }
    list[i] = tmp;

}

void heap_sort(int list[],int N)
{   
    int i,tmp;
    //建立初始大根堆
    for(i = N/2;i>=0;i--)
        percDown(list,i,N);
    //进行堆排序
    for(i=N-1;i>0;i--)
    {
        tmp = list[i];
        list[i] = list[0];
        list[0] = tmp;
        percDown(list,0,i);
    }   
}

int main()
{
    int list[6] = {34,8,64,51,32,21};
    int N = 6,i;
    heap_sort(list,N);
    for (i = 0;i< N ;i++)
    {
        printf("%3d",list[i]);
    }

}

如果你喜欢我写的文章,可以帮忙给小编点个赞或者加个关注,我一定会互粉的!
如果大家对数据结构感兴趣,欢迎跟小编进行交流,小编微信为sxw2251,加我要写好备注哟!:


数据结构与算法分析(c语言)--堆排序分析_第2张图片
我的微信

你可能感兴趣的:(数据结构与算法分析(c语言)--堆排序分析)