当前位置: 首页 > news >正文

数据结构(4) 堆

           堆(Heap)是一种非常重要的数据结构,在优先队列、堆排序、图算法等领域有着广泛的应用。本文将详细介绍堆的概念、特性以及如何在C、Java和Python中实现堆。


 一、堆的基本概念

堆是一种特殊的完全二叉树,它满足以下性质:
          1. 堆是一棵完全二叉树
          2. 堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点的值

堆可以分为两种:
         - 最大堆(大顶堆):每个节点的值都大于或等于其子节点的值
         - 最小堆(小顶堆):每个节点的值都小于或等于其子节点的值


 二、堆的存储方式

由于堆是完全二叉树,我们可以使用数组来高效地存储堆结构。对于数组中的任意一个位置i上的元素:

           - 其左子节点在位置:`2i + 1`
           - 其右子节点在位置:`2i + 2`
           - 其父节点在位置:`(i - 1) / 2`(整数除法)


 三、堆的核心操作

堆的核心操作包括:
    1. 插入元素:将新元素添加到堆的末尾,然后向上调整(heapify up)
    2. 删除堆顶元素:将堆顶元素与末尾元素交换,删除末尾元素,然后向下调整(heapify down)
    3. 构建堆:将一个无序数组构建成堆


 四、多语言实现

 1. C语言实现(最大堆)

```c
#include <stdio.h>
#include <stdlib.h>typedef struct {int *arr;int capacity;int size;
} MaxHeap;MaxHeap* createHeap(int capacity) {MaxHeap* heap = (MaxHeap*)malloc(sizeof(MaxHeap));heap->capacity = capacity;heap->size = 0;heap->arr = (int*)malloc(capacity * sizeof(int));return heap;
}void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}void heapifyUp(MaxHeap* heap, int index) {int parent = (index - 1) / 2;while (index > 0 && heap->arr[index] > heap->arr[parent]) {swap(&heap->arr[index], &heap->arr[parent]);index = parent;parent = (index - 1) / 2;}
}void heapifyDown(MaxHeap* heap, int index) {int left = 2 * index + 1;int right = 2 * index + 2;int largest = index;if (left < heap->size && heap->arr[left] > heap->arr[largest]) {largest = left;}if (right < heap->size && heap->arr[right] > heap->arr[largest]) {largest = right;}if (largest != index) {swap(&heap->arr[index], &heap->arr[largest]);heapifyDown(heap, largest);}
}void insert(MaxHeap* heap, int value) {if (heap->size == heap->capacity) {printf("Heap is full\n");return;}heap->arr[heap->size] = value;heapifyUp(heap, heap->size);heap->size++;
}int extractMax(MaxHeap* heap) {if (heap->size == 0) {printf("Heap is empty\n");return -1;}int max = heap->arr[0];heap->arr[0] = heap->arr[heap->size - 1];heap->size--;heapifyDown(heap, 0);return max;
}void buildHeap(MaxHeap* heap, int array[], int n) {for (int i = 0; i < n; i++) {insert(heap, array[i]);}
}void printHeap(MaxHeap* heap) {for (int i = 0; i < heap->size; i++) {printf("%d ", heap->arr[i]);}printf("\n");
}int main() {MaxHeap* heap = createHeap(10);int arr[] = {3, 2, 1, 5, 6, 4};buildHeap(heap, arr, 6);printf("Max heap: ");printHeap(heap);printf("Extracted max: %d\n", extractMax(heap));printf("Heap after extraction: ");printHeap(heap);insert(heap, 7);printf("Heap after inserting 7: ");printHeap(heap);free(heap->arr);free(heap);return 0;
}

 2. Java实现(最小堆)

import java.util.Arrays;public class MinHeap {private int[] heap;private int size;private int capacity;public MinHeap(int capacity) {this.capacity = capacity;this.size = 0;this.heap = new int[capacity];}private int parent(int index) {return (index - 1) / 2;}private int leftChild(int index) {return 2 * index + 1;}private int rightChild(int index) {return 2 * index + 2;}private void swap(int i, int j) {int temp = heap[i];heap[i] = heap[j];heap[j] = temp;}private void heapifyUp(int index) {while (index > 0 && heap[index] < heap[parent(index)]) {swap(index, parent(index));index = parent(index);}}private void heapifyDown(int index) {int minIndex = index;int left = leftChild(index);int right = rightChild(index);if (left < size && heap[left] < heap[minIndex]) {minIndex = left;}if (right < size && heap[right] < heap[minIndex]) {minIndex = right;}if (index != minIndex) {swap(index, minIndex);heapifyDown(minIndex);}}public void insert(int value) {if (size == capacity) {throw new IllegalStateException("Heap is full");}heap[size] = value;heapifyUp(size);size++;}public int extractMin() {if (size == 0) {throw new IllegalStateException("Heap is empty");}int min = heap[0];heap[0] = heap[size - 1];size--;heapifyDown(0);return min;}public void buildHeap(int[] array) {if (array.length > capacity) {throw new IllegalArgumentException("Array size exceeds heap capacity");}System.arraycopy(array, 0, heap, 0, array.length);size = array.length;for (int i = size / 2 - 1; i >= 0; i--) {heapifyDown(i);}}@Overridepublic String toString() {return Arrays.toString(Arrays.copyOf(heap, size));}public static void main(String[] args) {MinHeap heap = new MinHeap(10);int[] arr = {3, 2, 1, 5, 6, 4};heap.buildHeap(arr);System.out.println("Min heap: " + heap);System.out.println("Extracted min: " + heap.extractMin());System.out.println("Heap after extraction: " + heap);heap.insert(0);System.out.println("Heap after inserting 0: " + heap);}
}

 3. Python实现(最大堆)

class MaxHeap:def __init__(self, capacity):self.capacity = capacityself.size = 0self.heap = [0] * capacitydef parent(self, index):return (index - 1) // 2def left_child(self, index):return 2 * index + 1def right_child(self, index):return 2 * index + 2def swap(self, i, j):self.heap[i], self.heap[j] = self.heap[j], self.heap[i]def heapify_up(self, index):while index > 0 and self.heap[index] > self.heap[self.parent(index)]:self.swap(index, self.parent(index))index = self.parent(index)def heapify_down(self, index):max_index = indexleft = self.left_child(index)right = self.right_child(index)if left < self.size and self.heap[left] > self.heap[max_index]:max_index = leftif right < self.size and self.heap[right] > self.heap[max_index]:max_index = rightif index != max_index:self.swap(index, max_index)self.heapify_down(max_index)def insert(self, value):if self.size == self.capacity:raise Exception("Heap is full")self.heap[self.size] = valueself.heapify_up(self.size)self.size += 1def extract_max(self):if self.size == 0:raise Exception("Heap is empty")max_val = self.heap[0]self.heap[0] = self.heap[self.size - 1]self.size -= 1self.heapify_down(0)return max_valdef build_heap(self, array):if len(array) > self.capacity:raise Exception("Array size exceeds heap capacity")self.size = len(array)self.heap = array.copy()for i in range(self.size // 2 - 1, -1, -1):self.heapify_down(i)def __str__(self):return str(self.heap[:self.size])if __name__ == "__main__":heap = MaxHeap(10)arr = [3, 2, 1, 5, 6, 4]heap.build_heap(arr)print("Max heap:", heap)print("Extracted max:", heap.extract_max())print("Heap after extraction:", heap)heap.insert(7)print("Heap after inserting 7:", heap)

 五、堆的应用场景

1. 优先队列:堆是实现优先队列的理想数据结构
2. 堆排序:利用堆进行排序,时间复杂度为O(nlogn)
3. 图算法:如Dijkstra算法和Prim算法中用于高效获取最小/最大值
4. 求Top K问题:维护一个大小为K的堆可以高效解决Top K问题
5. 中位数查找:使用两个堆(最大堆和最小堆)可以高效查找中位数


 六、堆的时间复杂度分析

- 插入元素(insert):O(log n)
- 删除堆顶元素(extract):O(log n)
- 获取堆顶元素(peek):O(1)
- 构建堆(buildHeap):
  - 通过逐个插入:O(n log n)
  - 使用Floyd算法:O(n)


 七、总结

堆是一种高效的数据结构,特别适合需要频繁访问最大或最小元素的场景。通过本文的C、Java和Python实现,我们可以看到不同语言中堆的实现虽然语法不同,但核心逻辑是一致的。理解堆的原理和实现对于解决许多算法问题非常有帮助。

希望这篇文章能帮助你更好地理解堆数据结构。如果有任何问题,欢迎在评论区留言讨论!

相关文章:

  • Terraform 中的 external 数据块是什么?如何使用?
  • 软考-软件设计师中级备考 12、软件工程
  • Java 中使用 Callable 创建线程的方法
  • 【办公类-99-04】20250504闵豆统计表excle转PDF,合并PDF、添加中文字体页眉+边框下划线
  • postgresql数据库基本操作
  • JVM happens-before 原则有哪些?
  • 数字信号处理学习笔记--Chapter 1 离散时间信号与系统
  • AndroidLogger常用命令和搜索功能介绍
  • ESP32S3 多固件烧录方法、合并多个固件为单一固件方法
  • C语言实现数据结构:堆排序和二叉树_链式
  • 小土堆pytorch--tensorboard的使用
  • AI日报 · 2025年5月04日|Hugging Face 启动 MCP 全球创新挑战赛
  • 位置权限关掉还能看到IP属地吗?全面解析定位与IP的关系
  • nextjs+supabase vercel部署失败
  • 2025年第十六届蓝桥杯省赛B组Java题解【完整、易懂版】
  • GTID(全局事务标识符)的深入解析
  • better_fbx 下载
  • 金融信贷公司所需的技术和风控体系及其带来的价值
  • 个人文章不设置vip
  • 模型部署与提供服务
  • 遭反特朗普情绪拖累?澳大利亚联盟党大选落败、党魁痛失议席
  • 国际著名学者Charles M. Lieber全职受聘清华深圳国际研究生院
  • 中方拟解除对5名欧洲议会议员制裁?外交部:望中欧立法机构相向而行
  • 黄育奇当选福建惠安县人民政府县长
  • 海量数据处于“原矿”状态,数据价值释放如何破局?
  • 如何反击右翼思潮、弥合社会分裂:加拿大大选镜鉴