堆
大根堆
- 根节点是所有节点中数值最大的节点
- 父节点的值总比子节点大
- 基本操作
- Insert 向堆中插入一个值
- Update 更新
- Heapify 堆化
- RemoveTop 删除堆顶元素
- GetTop 获得堆顶元素
- 辅助操作
- 获得父节点
- 获得左孩子
- 获得右孩子
- 获得当前容量
- 判断一个节点是否是叶子节点
- 交换2个节点的位置
数组大根堆
- 用数组实现的大根堆
- 作用
- 基本操作
- Insert 向堆中插入一个值
- Update 从指定的节点开始把较大的值和父节点交换直到处理到根节点
- Heapify 从指定的节点开始把较小的节点和子节点中较大的那个交换直到处理到叶子节点
- RemoveTop 删除堆顶元素
- 把堆尾部的元素换到堆顶,堆大小-1
- 从堆顶开始执行堆化
- GetTop 获得堆顶元素
- 辅助操作
- 获得父节点
- 父节点和子节点的关系
- leftChildIndex = parentIndex * 2 + 1
- rightChildIndex = parentIndex * 2 + 2
- parentIndex = (childIndex - 1) / 2
- 获得左孩子
- 获得右孩子
- 获得当前容量
- 判断一个节点是否是叶子节点
- 如果一个节点的孩子index超过当前容量说明这个节点没有子节点,故为叶子节点
- 交换2个节点的位置
- 获得最大容量
- 根据index判断一个节点是否在堆中
- 实现代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DataStructure
{
public class ArrayMaxHeap
{
int[] array;
int size;
int maxSize;
public void Build(int maxSize)
{
array = new int[maxSize];
this.maxSize = maxSize;
size = 0;
}
public int GetSize()
{
return size;
}
public int GetMaxSize()
{
return maxSize;
}
//尾部追加再更新
public void Insert(int value)
{
if (size == maxSize)
{
throw new Exception("size must <= max size");
}
array[size] = value;
size++;
Update(size - 1);
}
//把大的值往堆顶放
//把一个大的值从下面换到父节点,直到堆顶
void Update(int index)
{
if (index == 0) return;
if (index < 0) throw new ArgumentException("index must >= 0");
if (array[index] > array[ParentIndex(index)])
{
Swape(index, ParentIndex(index));
Update(ParentIndex(index));
}
}
public int LeftChildIndex(int index)
{
return index * 2 + 1;
}
public int RightChildIndex(int index)
{
return index * 2 + 2;
}
public int ParentIndex(int index)
{
return (index - 1) / 2;
}
public bool IsLeaf(int index)
{
return !IsInHeap(LeftChildIndex(index));
}
public bool IsInHeap(int index)
{
return 0 <= index && index < size;
}
private void Swape(int index1, int index2)
{
var temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
public int GetTop()
{
return array[0];
}
void Heapify(int index)
{
if (IsLeaf(index))
{
return;
}
//找到左边和右边最大的那个子节点,如果子节点更大,交换,对子节点执行堆化,把小的值往堆底放
//左子节点更大
if (array[LeftChildIndex(index)] > array[RightChildIndex(index)])
{
if (array[index] < array[LeftChildIndex(index)])
{
Swape(index, LeftChildIndex(index));
Heapify(LeftChildIndex(index));
}
}
//右孩子更大,比较右孩子
else if (array[index] < array[RightChildIndex(index)])
{
Swape(index, RightChildIndex(index));
Heapify(RightChildIndex(index));
}
}
//取出堆顶,把尾部放到堆顶,执行堆化
public int RemoveTop()
{
if (size == 0) throw new Exception("no element in heap");
var top = array[0];
array[0] = array[size - 1];
size--;
Heapify(0);
return top;
}
public static void Test()
{
var array = new int[] { 2, 4, 6, 7, 8, 3, 2, 5 };
var solution = new ArrayMaxHeap();
solution.Build(array.Length);
foreach (var num in array)
{
solution.Insert(num);
BaseSolution.print(solution.GetTop());
BaseSolution.print(',');
}
BaseSolution.println();
while (solution.GetSize() > 0)
{
BaseSolution.print(solution.RemoveTop());
BaseSolution.print(',');
}
}
}
}