堆是一颗被完全填满的二叉树,它的任一结点的关键字是其子树所有结点的最大值或最小值,
最大值的则是最大堆,也称大顶堆,最小值的则是最小堆,也称小顶堆。
比如:
最小堆C/C++实现
#pragma once
#include <vector>
#include <initializer_list>
template <typename Comparable>
class MinHeap
{
public:
explicit MinHeap(int capacity = 100) :array(capacity + 10), currentSize(0) {}
explicit MinHeap(const std::vector<Comparable> & items);
bool isEmpty()const { return array.size() == 0; }
const Comparable & findMin()const { return array[1]; }
void insert(const Comparable & x);
void insert(std::initializer_list<Comparable>t);
void deleteMin();
void deleteMin(Comparable & minItem);
void makeEmpty() { array.swap(vector<Comparable>()); }
private:
int currentSize;
std::vector<Comparable>array;
void buildHeap();
void Sink(int hole);//下沉
};
template<typename Comparable>
MinHeap<Comparable>::MinHeap(const std::vector<Comparable>& items):array(items.size()+10),currentSize(items.size())
{
for (int i = 0; i < items.size(); i++)
array[i + 1] = items[i];
buildHeap();
}
template<typename Comparable>
void MinHeap<Comparable>::insert(const Comparable & x)
{
if (currentSize == array.size() - 1)
{
array.resize(array.size() * 2);
}
int hole = ++currentSize;
Comparable copy = x;
array[0] = std::move(copy);//保存原来的值
for (; x < array[hole / 2]; hole /= 2)//如果x更小,就一直上浮
{
array[hole] = std::move(array[hole / 2]);//交换
}
array[hole] = std::move(array[0]);//空穴找到了合适的位置,把原来的值放进去.
}
template<typename Comparable>
void MinHeap<Comparable>::insert(std::initializer_list<Comparable>t)
{
for (auto p = t.begin(); p != t.end(); p++)
{
insert(*p);
}
}
template<typename Comparable>
void MinHeap<Comparable>::deleteMin()
{
if (isEmpty())
{
std::cout << "Heap Is Empty!" << std::endl;
return;
}
array[1] = std::move(array[currentSize--]);
Sink(1);
}
template<typename Comparable>
void MinHeap<Comparable>::deleteMin(Comparable & minItem)
{
if (isEmpty())
{
std::cout << "Heap Is Empty!" << std::endl;
return;
}
minItem = std::move(array[1]);
array[1] = std::move(array[currentSize--]);//从数组顶端删去最小的元素,并将数组最后的一个元素放到顶端
Sink(1);//然后让这个元素下沉
}
template<typename Comparable>
void MinHeap<Comparable>::buildHeap()
{
for (int i = currentSize / 2; i > 0; --i)
{
Sink(i);
}
}
template<typename Comparable>
void MinHeap<Comparable>::Sink(int hole)//下沉
{
int child;
Comparable temp = std::move(array[hole]);
for (; hole * 2 <= currentSize; hole = child)
{
child = hole * 2;
if (child != currentSize && array[child + 1] < array[child])//右边更小,往右沉
++child;
if (array[child] < temp)//比目标值小,当前child上浮
array[hole] = std::move(array[child]);
else //比目标值大,或相等,找到合适的位置,退出循环
break;
}
array[hole] = std::move(temp);
}
最大堆C#实现
public class MaxHeap<T> where T : IComparable<T>
{
private T[] array;
private int CurrentSize { set; get; }
public MaxHeap(int capacity = 100)
{
array = new T[capacity];
CurrentSize = 0;
}
public MaxHeap(T[] items)
{
array = new T[items.Length + 10];
for (int i = 0; i < items.Length; i++)
{
array[i + 1] = items[i];
}
}
public bool IsEmpty(){ return array.Length == 0; }
public T Max() { return array[1]; }
public void Insert( T x)
{
if(CurrentSize == array.Length -1)
{
T[] temp = array;
array = new T[array.Length * 2];
for(int i = 0; i < temp.Length;i++)
{
array[i + 1] = temp[i + 1];
}
temp = null;
}
int hole = ++CurrentSize;
array[0] = x;
for (; array[hole / 2].CompareTo(x) < 0;hole /=2)
{
array[hole] = array[hole / 2];
}
array[hole] = array[0];
}
public void Insert(params T[] paramList)
{
foreach (T temp in paramList)
{
Insert(temp);
}
}
public void DeleteMax()
{
if(IsEmpty())
{
throw new Exception("Heap Is Empty!\n");
}
array[1] = array[CurrentSize--];
Sink(1);
}
public void DeleteMax(out T temp)
{
if (IsEmpty())
{
throw new Exception("Heap Is Empty!\n");
}
temp = array[1];
array[1] = array[CurrentSize--];
Sink(1);
return;
}
private void BuildHeap()
{
for (int i = CurrentSize / 2; i > 0; --i)
{
Sink(i);
}
}
private void Sink(int hole)
{
int child;
T temp = array[hole];
for(; hole *2 <= CurrentSize; hole = child)
{
child = hole * 2;
if (child != CurrentSize && array[child].CompareTo(array[child + 1]) < 0)
++child; //child指向左右子节点的较大者
if (temp.CompareTo(array[child]) < 0)
array[hole] = array[child];
else
break;
}
array[hole] = temp;
}
}