首页 > 其他分享 >堆排序|维护堆和建堆

堆排序|维护堆和建堆

时间:2024-06-20 18:56:37浏览次数:12  
标签:nums int 建堆 printf 堆排序 flag largest 维护 节点

堆可以看作各个元素之前有前后续的特殊数组,当然也是一颗完全二叉树。设堆heap的元素为heap[1,2,3,...,heap_size]。注意0<=heap_size<=heap.len,并且节点从1开始计数(便于计算)。

1. 寻找节点

1.1 寻找父节点

若节点编号为 i i i,那么他的父节点为 i 2 \frac{i}{2} 2i​向下取整。代码实现如下:

/**
 * 求节点i的父节点
 */
int parent(int i){
    return i/2;
}

1.2 寻找左孩子

若节点编号为 i i i,那么他的左孩子节点为 2 i 2i 2i。代码实现如下:

/**
 * 求左孩子
 */
int left(int i){
    return 2*i;
}

1.3 寻找右孩子

若节点编号为 i i i,那么他的左孩子节点为 2 i 2i 2i+1。代码实现如下:

/**求右孩子 
 * 
*/
int right(int i){
    return 2*i+1;
}

2. 维护堆

  • 在堆nums中维护第i个节点为根的树

参数说明:

  • nums:表示待维护的堆
  • i表示待维护的节点
  • 返回值若为1则说明该堆被维护过,返回值为0则说明该堆不需要被维护
  • 注:堆的第一个元素nums[0]存储堆内有效数据的长度,建堆的时候应该明确给出
  • 使用flag来监视程序是否更改堆的顺序
int maxHeapIfy(int nums[], int i){
    int l = left(i);
    int r = right(i);
    int largest;
    int heapSize = nums[0];

    //flag用于判断是否被维护过
    int flag = 0;

    //判断左子树和根节点哪个大,选出大的节点设为largest
    if(l <= nums[0] && nums[l]>nums[i]){
        largest = l;
    }else{
        largest = i;
    }

    //比较largest和右节点那个大,选出大节点作为largest
    if( r <= nums[0] && nums[r]>nums[largest]){
        largest = r;
    }

    //若largest != i则说明该节点为根的树需要调整
    if(largest != i){
        flag=1;
        int exchange;
        exchange = nums[largest];
        nums[largest] = nums[i];
        nums[i] =  exchange;

        maxHeapIfy(nums , largest);
    }
    
    return flag;
}

3. 建堆

直接按照输入数组,从最后一个非叶子节点开始(一直到第一个节点)调用维护堆的函数,即可根据输入数组建立一个最大堆。

/**
 * 建堆,nums[0]表示第堆的大小
 * 
 * 
 */
void buildMaxHeap(int nums[]){
    for(int i=nums[0]/2;i>0;i--){
        maxHeapIfy(nums,i);
    }
}

4. 测试

4.1 测试代码

#include<stdio.h>
#include"tools.h"
#include"tets.h"
int main(){
    int s[]={0,2,7,2,9,100,3,6};
    s[0] = sizeof(s)/sizeof(s[0])-1;
    
    printf("原始堆顺序如下:\n");
    for(int i = 1;i<8;i++){
        printf("%d  ",s[i]);
    }
    printf("\n堆的大小为:%d \n",s[0]);

    buildMaxHeap(s);

    int flag = maxHeapIfy(s,1);

    printf("flag:%d \n",flag);

    printf("排序后的堆顺序如下:\n");
    for(int i = 1;i<8;i++){
        printf("%d  ",s[i]);
    }
    return 0;
}

4.2 测试结果

在这里插入图片描述

5. 时间复杂度

维护堆时间复杂度: O ( log ⁡ n ) = O ( h ) O(\log n)=O(h) O(logn)=O(h)( h h h即待维护节点的高度)
建堆时间复杂度: O ( n ) O(n) O(n)

标签:nums,int,建堆,printf,堆排序,flag,largest,维护,节点
From: https://blog.csdn.net/qq_54259059/article/details/139839984

相关文章

  • 淘宝二面:千万级数据中如何用Redis维护热点数据"?
    MySQL里有千万条数据,但是Redis中只存10万的数据,如何保证redis中的数据都是热点数据?......
  • 论如何使用机器学习,预测客户流失率,轻松实现客户精准维护
    01、案例说明首先我们学习最经典的机器学习模型,就是监督学习(SupervisedLearning)中的分类模型。这边使用的是一个电信公司的案例,通过客户的基本资料和一些简单的互动信息,建立一个模型,以预测哪些客户有较高的可能性流失,从而进行补救。因为研究显示得到一个新客户的成本是维......
  • 如何利用 Perl 高效地构建和维护复杂的 Web 应用程序,以及与当前主流的 Web 框架和技术
    Perl是一种通用的脚本语言,可用于构建和维护复杂的Web应用程序。以下是利用Perl高效构建和维护复杂的Web应用程序的一些建议:使用现代化的Web框架:Perl有一些流行的Web框架,例如Dancer、Mojolicious和Catalyst。这些框架提供了丰富的功能和工具,可以快速开发和......
  • 4-十五章 系统运行与维护(完结篇)
    其他章节内容多有重复,故不再赘述15.1遗留系统的处理策略:是指任何基本上不能进行修改和演化以满足新的变化了的业务需求的信息系统,通常具有以下特点:1)系统虽然完成企业中许多重要的业务管理工作,但仍然不能完全满足要求。一般实现业务处理电子化及部分企业管理功能,很少涉及经营......
  • 【服务器硬件由 CPU、RAM、硬盘等组成,选购时需考虑应用需求、预算等。散热、安全、监
    本人详解作者:王文峰,参加过CSDN2020年度博客之星,《Java王大师王天师》公众号:JAVA开发王大师,专注于天道酬勤的Java开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯山峯转载说明:务必注明来源(注明:作者:王文峰哦)【服务器硬件......
  • 哪些方法可以让 Python 代码易维护
    随着软件项目进入“维护模式”,对可读性和编码标准的要求很容易落空(甚至从一开始就没有建立过那些标准)。然而,在代码库中保持一致的代码风格和测试标准能够显著减轻维护的压力,也能确保新的开发者能够快速了解项目的情况,同时能更好地全程保持应用程序的质量。使用外部库来检查代......
  • SFC命令的基本用法,以及处理基本系统文件问题的能力,为系统维护和故障排除提供基础支持;S
    SFC命令初级应用大纲1.理解SFC命令命令简介:了解SFC(SystemFileChecker)命令的作用和基本原理。掌握SFC命令的基本语法和用法。2.执行基本系统文件检查运行SFC扫描:学习如何以管理员身份在命令提示符或Powershell中运行SFC扫描。理解SFC扫描的过程和输出。解......
  • 好车、好团队、好圈子:制造、使用与维护的艺术
     在这个充满协作与互动的时代,我们可以把团队和圈子看作是一辆辆行驶在人生道路上的车辆,每个成员都扮演着车上不可或缺的零部件角色。想要获得一辆性能出色的车,我们需要在制造、使用和维护上付出相应的努力。同样,为了构建一个高效的团队或一个有活力的圈子,我们也需要在创建、......
  • 数据结构学习笔记-堆排序
    堆排序算法的设计与分析问题描述:设计并分析堆排序【前置知识:什么是堆?】堆(Heap)是一种特殊的树形数据结构,它满足以下两个条件之一:最大堆(MaxHeap):每个节点的值都大于或等于其子节点的值。换句话说,根节点的值是整个堆中最大的。最小堆(MinHeap):每个节点的值都小于或等于其......
  • 维护一个对象只能通过new来创建,且要实现对象能够自动销毁的单例代码实现及扩展。
    结论:析构函数设为私有且在单例类的内部维护一个Chelper类。(如果是单例,还要将构造函数设为私有,如果是可以在全局有多个实例但是希望只能提供new创建,则构造必须公有且必须提供成员函数来调用deletethis来调用该对象的析构函数)。具体细节可看代码解释部分。代码实现:test.hcla......