数据结构===堆

简介: 数据结构===堆

概要

堆,有趣的数据结构。

那么,如何实现一个堆呢?

堆,有哪些重点:

  1. 满足2条件
  2. 大顶堆
  3. 小顶堆

2条件

2条件:

  1. 堆是一个完全二叉树
  2. 堆中的每个节点的值都必须大于等于或小于等于其树中每个节点的值

堆要满足这2个条件,重点。即使后边插入数据,或者删除数据之后,还是要满足这2个条件来做调整。

大顶堆

特点:

每个节点的值都大于等于子树中每个节点值的堆。

小顶堆

特点:

每个节点的值都小于等于子树中每个节点值的堆。

堆的实现

实现一个堆,重要的操作:插入元素和删除堆顶元素

插入元素

堆化:顺着节点所在的路径,向上或者向下,对比,然后交换。

来看下插入的代码:

public class Heap {
  private int[] a; // 数组,从下标1开始存储数据
  private int n;  // 堆可以存储的最大数据个数
  private int count; // 堆中已经存储的数据个数
  public Heap(int capacity) {
    a = new int[capacity + 1];
    n = capacity;
    count = 0;
  }
  public void insert(int data) {
    if (count >= n) return; // 堆满了
    ++count;
    a[count] = data;
    int i = count;
    while (i/2 > 0 && a[i] > a[i/2]) { // 自下往上堆化
      swap(a, i, i/2); 
      i = i/2;
    }
  }
 }

删除堆顶元素

由大顶堆和小顶堆的定义可知,堆顶元素要么最大,要么最小;

public void removeMax() {
  if (count == 0) return -1; // 堆中没有数据
  a[1] = a[count];
  --count;
  heapify(a, count, 1);
}
private void heapify(int[] a, int n, int i) { // 自上往下堆化
  while (true) {
    int maxPos = i;
    if (i*2 <= n && a[i] < a[i*2]) maxPos = i*2;
    if (i*2+1 <= n && a[maxPos] < a[i*2+1]) maxPos = i*2+1;
    if (maxPos == i) break;
    swap(a, i, maxPos);
    i = maxPos;
  }
}

堆代码

来看个完整的代码吧,这里给python的。如下:

import sys 
class BinaryHeap:
  def __init__(self, capacity):
    self.capacity = capacity
    self.size = 0
    self.Heap = [0]*(self.capacity + 1)
    self.Heap[0] = -1 * sys.maxsize
    self.FRONT = 1
  
  def parent(self, pos):
    return pos//2
  
  def leftChild(self, pos):
    return 2 * pos       
  
  def rightChild(self, pos):
    return (2 * pos) + 1
  def isLeaf(self, pos):
  if pos >= (self.size//2) and pos <= self.size:
    return True
  return False
def swap(self, fpos, spos):
  self.Heap[fpos], self.Heap[spos] = self.Heap[spos], self.Heap[fpos]
def heapifyDown(self, pos):
  if not self.isLeaf(pos):
    if (self.Heap[pos] > self.Heap[self.leftChild(pos)] or self.Heap[pos] > self.Heap[self.rightChild(pos)]):
      if self.Heap[self.leftChild(pos)] < self.Heap[self.rightChild(pos)]:
        self.swap(pos, self.leftChild(pos))
        self.heapifyDown(self.leftChild(pos))
      else:
        self.swap(pos, self.rightChild(pos))
        self.heapifyDown(self.rightChild(pos))
def insert(self, element):
  if self.size >= self.capacity :
    return
  self.size+= 1
  self.Heap[self.size] = element
  
  current = self.size
  while self.Heap[current] < self.Heap[self.parent(current)]:
    self.swap(current, self.parent(current))
    current = self.parent(current)
def minHeap(self):
  for pos in range(self.size//2, 0, -1):
    self.heapifyDown(pos)
def delete(self):
  popped = self.Heap[self.FRONT]
  self.Heap[self.FRONT] = self.Heap[self.size]
  self.size-= 1
  self.heapifyDown(self.FRONT)
  return popped
def isEmpty(self):
  return self.size == 0
def isFull(self):
  return self.size == self.capacity

小结

关于堆,就这么多吧

堆的概念跟推理还是相对来说简单的。比红黑树简单点。其实都一样的,只要按照那些规则,一条一条对着去理解;应该还好。

相关文章
|
23天前
|
存储 算法 Java
散列表的数据结构以及对象在JVM堆中的存储过程
本文介绍了散列表的基本概念及其在JVM中的应用,详细讲解了散列表的结构、对象存储过程、Hashtable的扩容机制及与HashMap的区别。通过实例和图解,帮助读者理解散列表的工作原理和优化策略。
30 1
散列表的数据结构以及对象在JVM堆中的存储过程
|
25天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
63 16
|
2月前
|
存储 JavaScript 前端开发
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
72 1
|
3月前
|
存储 Java
【数据结构】优先级队列(堆)从实现到应用详解
本文介绍了优先级队列的概念及其底层数据结构——堆。优先级队列根据元素的优先级而非插入顺序进行出队操作。JDK1.8中的`PriorityQueue`使用堆实现,堆分为大根堆和小根堆。大根堆中每个节点的值都不小于其子节点的值,小根堆则相反。文章详细讲解了如何通过数组模拟实现堆,并提供了创建、插入、删除以及获取堆顶元素的具体步骤。此外,还介绍了堆排序及解决Top K问题的应用,并展示了Java中`PriorityQueue`的基本用法和注意事项。
58 5
【数据结构】优先级队列(堆)从实现到应用详解
|
2月前
|
存储 算法 调度
数据结构--二叉树的顺序实现(堆实现)
数据结构--二叉树的顺序实现(堆实现)
|
2月前
|
存储 算法 分布式数据库
【初阶数据结构】理解堆的特性与应用:深入探索完全二叉树的独特魅力
【初阶数据结构】理解堆的特性与应用:深入探索完全二叉树的独特魅力
|
2月前
|
存储 算法
探索数据结构:分支的世界之二叉树与堆
探索数据结构:分支的世界之二叉树与堆
|
2月前
|
存储 算法 Java
【用Java学习数据结构系列】用堆实现优先级队列
【用Java学习数据结构系列】用堆实现优先级队列
32 0
|
2月前
|
存储 算法
【数据结构】二叉树——顺序结构——堆及其实现
【数据结构】二叉树——顺序结构——堆及其实现
|
2月前
【数据结构】大根堆和小根堆
【数据结构】大根堆和小根堆
37 0