数据结构学习记录——堆的建立(最大堆的建立、思路图解、代码实现、代码解释)

简介: 数据结构学习记录——堆的建立(最大堆的建立、思路图解、代码实现、代码解释)

最大堆的建立

建立最大堆:将已经存在的N个元素按最大堆的要求存放在一个一维数组中。

方法1

通过插入操作,将N个元素一个一个地插入到一个初始为空的堆中去。堆插入的时间复杂度为log2N2,插人N个元素,那么最终建立堆的时间复杂度就为O(Nlog2N)(2)

方法2

线性时间复杂度下建立最大堆。

(1)将N个元素按输入顺序存入,先满足完全二叉树的结构特性

(2)调整各结点位置,以满足最大堆的有序性

我们当然要选择更高效率的方法,下面就来看看方法2具体是怎样实现的:

思路图解

假设现在有12个元素,已经按输入顺序存入,满足了完全二叉树的结构特性:

对其进行调整,调整的思路和堆的删除相似,但是要从后往前开始,在左右两个堆中进行调整;我们从倒数第一个有儿子的结点开始调整。因为倒数第一个结点一定是只有左儿子或者有一个左儿子和一个右儿子,即左右两边一定是堆的结构

调整完倒数第一个有儿子 的结点之后,往上再进行调整。

重复操作

继续往上,到上一层了。  

循环


最终调整完成 :

代码实现

/* 下滤操作:将H中以H->Data[p]为根的子堆调整为最大堆 */
void PercDown( MaxHeap H, int p )
{ 
    int Parent, Child;
    ElementType X;
 
    X = H->Data[p]; /* 取出根结点存放的值 */
    for( Parent=p; Parent*2<=H->Size; Parent=Child )
    {
        Child = Parent * 2;
        if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
        {
            Child++;  /* Child指向左右子结点的较大者 */
        }
        if( X >= H->Data[Child] ) 
        {
            break; /* 找到了合适位置 */
        }
        else
        {
            /* 下滤X */
            H->Data[Parent] = H->Data[Child];
        } 
    }
    H->Data[Parent] = X;
}
 
/* 将一个无序的数组调整为最大堆  */
void BuildHeap( MaxHeap H )
{ 
  /* 这里假设所有H->Size个元素已经存在H->Data[]中 */
 
    int i;
 
    /* 从最后一个结点的父节点开始,到根结点1 */
    for( i = H->Size/2; i>0; i-- )
        PercDown( H, i );
}

代码解释

PercDown

PercDown函数用于将以某个结点为根的子树调整为最大堆。

其中,参数p,表示要下滤的结点在H中的下标。

Parent表示当前结点的父结点,Child表示当前结点的子结点,X表示当前结点的值。

首先,将要下滤的结点的值X取出来,保存在一个临时变量中。

然后,从要下滤的结点开始,沿着其左右子结点中较大的一个不断下滤,


直到找到X的合适位置或者到达叶结点为止。(Child的判断那里与堆的删除那里是一致的)


具体来说,每次将要下滤的结点与其左右子结点中较大的一个进行比较,


如果X比较大,则说明X已经找到了合适的位置,可以退出循环;(最大堆根结点比左右子结点都要大)

否则,将较大的子节点上移一层,继续下滤。

最后,将X放到找到的合适位置上,完成下滤操作。

BuildHeap

BuildHeap函数用于将一个无序的数组调整为最大堆。

从倒数第一个没有儿子的结点开始,即从最后一个非叶子节点开始,依次进行下滤操作,将其子树调整为最大堆。

因为最后一个非叶子节点的数组下标为n/2,其中n为堆中元素的个数,所以从i=n/2开始循环。

循环执行,直到整个数组都被调整为最大堆。

综上,BuildHeap函数的时间复杂度为O(N),其中N为堆中元素的个数。因为每个结点最多只需要下滤一次,而下滤的时间复杂度为O(log2N),所以建立一个最大堆,总的时间复杂度为O(Nlog2N)。与开头所说相符合,效率较方法1要更高。



end



目录
相关文章
|
7月前
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
243 1
|
8月前
|
算法 数据可视化 开发者
为什么要学习数据结构与算法
今天,我向大家介绍一门非常重要的课程——《数据结构与算法》。这门课不仅是计算机学科的核心,更是每一位开发者从“小白”迈向“高手”的必经之路。
为什么要学习数据结构与算法
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
565 16
|
12月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
412 1
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习(8)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法

热门文章

最新文章