热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

堆排序与数据结构中的堆

堆是一种常见的数据结构,广泛应用于计算机科学领域。它通常表示为一棵完全二叉树,并可通过数组实现。堆的主要特性是每个节点的值与其父节点的值之间存在特定的关系,这使得堆在优先队列和排序算法中非常有用。
堆(heap)是一种特殊的数据结构,其特点是可以通过数组来表示一棵完全二叉树。堆的主要性质包括:

1. **父子节点关系**:对于最大堆,每个节点的值都不小于其子节点的值;对于最小堆,每个节点的值都不大于其子节点的值。
2. **完全二叉树**:堆总是一棵完全二叉树,这意味着除了最后一层外,所有层都是满的,且最后一层的节点尽可能靠左排列。

### 堆的分类

根据根节点的值,堆可以分为两种类型:
- **最大堆(大顶堆)**:根节点是堆中最大的元素。
- **最小堆(小顶堆)**:根节点是堆中最小的元素。

常见的堆实现包括二叉堆、斐波那契堆等。二叉堆是最常用的堆实现方式之一,它通过数组存储,并且满足以下条件:

设一个包含n个元素的序列{k1, k2, ..., kn},当且仅当满足以下关系时,该序列为堆:

- 对于最大堆:ki >= k2i 和 ki >= k2i+1 (i = 1, 2, ..., n/2)
- 对于最小堆:ki <= k2i 和 ki <= k2i+1 (i = 1, 2, ..., n/2)

### 堆的操作

堆支持多种操作,包括但不限于:

- **build**:创建一个空堆。
- **insert**:向堆中插入新元素。
- **update**:调整新元素的位置以保持堆的性质。
- **get**:获取当前堆顶元素的值。
- **delete**:删除堆顶元素。
- **heapify**:在删除堆顶元素后重新调整堆以保持其性质。

某些堆实现还支持其他操作,如检查堆中是否存在某个元素。

### 建堆效率

对于包含n个节点的堆,高度d = log₂n。建堆的时间复杂度为O(n),因为大部分节点位于树的底部,而这些节点不需要移动。插入、删除普通元素和删除最小元素的平均时间复杂度为O(log n)。

### 堆的应用

堆广泛用于动态内存分配和释放,特别是在程序需要动态分配对象时。例如,当程序所需对象的数量和大小事先未知,或对象太大不适合使用栈分配器时,堆是一个很好的选择。

在操作系统和运行时库中,堆用于管理进程内的内存分配。默认情况下,操作系统会为每个进程创建一个称为进程堆的默认堆。此外,应用程序或加载的动态链接库(DLL)也可以创建并使用单独的堆。

### 代码实现示例

以下是一个最小堆的C++实现:

```cpp
#pragma once
template
class MinHeap {
private:
T* _heap;
int _size;
int _capacity;

public:
MinHeap(int capacity) : _capacity(capacity), _size(0) {
_heap = new T[_capacity];
}

~MinHeap() {
delete[] _heap;
}

bool isEmpty() const {
return _size == 0;
}

bool isFull() const {
return _size == _capacity;
}

bool add(const T& value) {
if (isFull()) {
return false;
}
_heap[_size++] = value;
adjustUp(_size - 1);
return true;
}

void adjustDown(int index) {
int smallest = index;
int left = 2 * index + 1;
int right = 2 * index + 2;

if (left <_size && _heap[left] <_heap[smallest]) {
smallest = left;
}
if (right <_size && _heap[right] <_heap[smallest]) {
smallest = right;
}

if (smallest != index) {
std::swap(_heap[index], _heap[smallest]);
adjustDown(smallest);
}
}

void adjustUp(int index) {
while (index > 0 && _heap[(index - 1) / 2] > _heap[index]) {
std::swap(_heap[(index - 1) / 2], _heap[index]);
index = (index - 1) / 2;
}
}
};
```

此代码实现了最小堆的基本功能,包括插入和调整操作。
推荐阅读
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 本文介绍了如何在C#中启动一个应用程序,并通过枚举窗口来获取其主窗口句柄。当使用Process类启动程序时,我们通常只能获得进程的句柄,而主窗口句柄可能为0。因此,我们需要使用API函数和回调机制来准确获取主窗口句柄。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 本文探讨了如何优化和正确配置Kafka Streams应用程序以确保准确的状态存储查询。通过调整配置参数和代码逻辑,可以有效解决数据不一致的问题。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 使用GDI的一些AIP函数我们可以轻易的绘制出简 ... [详细]
  • 作者:守望者1028链接:https:www.nowcoder.comdiscuss55353来源:牛客网面试高频题:校招过程中参考过牛客诸位大佬的面经,但是具体哪一块是参考谁的我 ... [详细]
  • 20100423:Fixes:更新批处理,以兼容WIN7。第一次系统地玩QT,于是诞生了此预备式:【QT版本4.6.0&#x ... [详细]
  • 本文详细介绍了如何在C#程序运行期间防止系统进入休眠模式以及显示器关闭,提供了具体的实现代码示例,并解释了其应用场景。这不仅有助于提高程序的稳定性,还能优化能源管理。适合需要处理长时间任务(如下载或批处理)的开发者参考。 ... [详细]
  • 阿里云ecs怎么配置php环境,阿里云ecs配置选择 ... [详细]
  • ElasticSearch 集群监控与优化
    本文详细介绍了如何有效地监控 ElasticSearch 集群,涵盖了关键性能指标、集群健康状况、统计信息以及内存和垃圾回收的监控方法。 ... [详细]
  • 本文介绍了一种基于选择排序思想的高效排序方法——堆排序。通过使用堆数据结构,堆排序能够在每次查找最大元素时显著提高效率。文章详细描述了堆排序的工作原理,并提供了完整的C语言代码实现。 ... [详细]
  • KMP算法是一种高效的字符串模式匹配算法,能够在不进行回溯的情况下完成匹配,其时间复杂度为O(m+n),其中m和n分别为文本串和模式串的长度。本文将详细介绍KMP算法的工作原理,并提供C语言实现。 ... [详细]
author-avatar
洗个小枣_312
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有