算法导论-第六章-堆排序

本文介绍了堆排序这种基于完全二叉树的顺序存储数据结构。堆排序的时间复杂度为O(nlgn),分为大顶堆和小顶堆,分别适用于升序和降序排列。维护和建立堆的操作分别需要O(lgn)和O(n)时间,而排序过程则为O(nlgn)。作者强调理解算法背后的思维,并推荐通过阅读专业书籍来深入学习。

这里的堆其实是一种采用顺序存储的数据结构
且采用树型的表现形式(完全二叉树),至于完全二叉树以什么样的形式存储在数组中,请参考数据结构相关的书籍。下面直接给出完全二叉树中父结点与左右孩子的关系。

int record[1000];//存储二叉树所有结点的数组
int root;//某子树的一根结点
int Lchild=2*root;//record数组中,root的左孩子所在下标
int Rchild=2*root+1//record数组中,root的左孩子所在下标

对于大顶堆,父结点的值大于孩子结点的值。小顶堆,父结点的值小与孩子结点的值。采用堆排序的时间复杂度为O(nlgn),且为原址排序。

维护大顶堆O(lgn)

//维护子树,使其保持大顶堆的性质。递归维护
void MAX_HEAPIFY(int *a, int root,int len)
{
    int l=2*root;
    int r=l+1;
    int largest=root;
    //选择父结点,左右孩子结点中,值最大的结点,并用largest记录下表编号
    if(l<len&&a[l]>a[root])
        largest=l;
    if(r<len&&a[r]>a[largest])
        largest=r;
    //不符合大顶堆的性质,向下递归修正
    if(largest!=root)
    {
        int temp=a[root];
        a[root]=a[largest];
        a[largest]=temp;
        MAX_HEAPIFY(a,largest,len);
    }
}

建立大顶堆O(n)注意不是O(nlgn)推导过程很复杂

void BUILD_MAXHEAP(int *a,int len)
{
	//自下而上,从叶子结点开始遍历二叉树,维护大顶堆
    for(int i=len-1; i>=0; i--)
    {
        MAX_HEAPIFY(a,i,len);
    }
}

对大顶堆排序(升序排列)O(nlgn)

void SORT_MAXHEAP(int *a,int len)
{
//每次取出堆顶元素与数组末尾元素交换,并将数组长度减一,维护大顶堆。最终得到升序排列的数组
    while(len>1)
    {
        len--;
        int temp=a[len];
        a[len]=a[0];
        a[0]=temp;
        MAX_HEAPIFY(a,0,len);
    }
    MAX_HEAPIFY(a,0,1);
}

小顶堆维护O(lgn)

void MIN_HEAPIFY(int *a,int root,int len)
{
    int l=2*root;
    int r=l+1;
    int smallest=root;
    if(l<len&&a[l]<a[root])
        smallest=l;
    if(r<len&&a[r]<a[smallest])
        smallest=r;
    if(smallest!=root)
    {
        int temp=a[root];
        a[root]=a[smallest];
        a[smallest]=temp;
        MIN_HEAPIFY(a,smallest,len);
    }
}

小顶堆建立O(n)

void BUILD_MINHEAP(int *a,int len)
{
    for(int i=len-1; i>=0; i--)
    {
        MIN_HEAPIFY(a,i,len);
    }
}

小顶堆排序O(nlgn)

void SORT_MINHEAP(int *a,int len)
{
    while(len>1)
    {
        len--;
        int temp=a[len];
        a[len]=a[0];
        a[0]=temp;
        MIN_HEAPIFY(a,0,len);
    }
    MIN_HEAPIFY(a,0,1);
}

我写的这些博客,也只是业余爱好,加深自己对知识的理解。现在网上的博客越来越多,鱼龙混杂。建议大家还是认真的去读书,尝试理解真正的大牛是怎么思考问题的。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值