数据结构===堆

本文介绍了堆这种有趣的数据结构,包括大顶堆和小顶堆的特点,以及如何通过代码实现插入元素和删除堆顶元素的操作。通过Python示例展示了堆的完整实现过程,强调了堆化在保持堆性质中的关键作用。

概要

堆,有趣的数据结构。

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

堆,有哪些重点:

  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

小结

关于堆,就这么多吧

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

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值