堆是一种特殊类型的二叉树,具有以下两个性质:
1. 每个节点的值大于/小于(最大堆/最小堆)等于其每个子节点的值
2. 该数完全平衡,最后一层的叶子都处于最左侧的位置
本文以最大堆为例子,实现堆的插入与删除操作.其中,堆的插入操作总是在最后的位置,删除操作总是在开头的位置.有些与队列的先进先出相似.
代码实现如下:
其中,利用数组来实现堆,数组的下标天然的可以对应堆的层次结构.若父节点下标为i,则左右子节点下标必然为2*i+1与2*i+2.
堆的插入总是在最后位置,插入后,对该位置进行上移交换,直到满足堆特性为止.删除时,总是删除根节点数据,然后将最后节点数据放入根节点,从根节点开始做向下交换,直到满足堆特性为止.
#ifndef _HEAP_H_
#define _HEAP_H_
#include "Constant.h"
template <class T>
struct HeapNode
{
T data; //data
};
template <class T, unsigned int capacity>
class Heap
{
public:
Heap();
~Heap();
void AddElem(T value);
void deleteElem(T &value);
bool isFull();
bool isEmpty();
private:
HeapNode<T>** heapArray;
unsigned int elemNum;
};
#endif
#include "Heap.h"
template <class T, unsigned int capacity>
Heap<T, capacity>::Heap()
{
elemNum = 0;
heapArray = new HeapNode<T>*[capacity];
}
template <class T, unsigned int capacity>
Heap<T, capacity>::~Heap()
{
if (elemNum > 0)
{
for (int i = 0; i < elemNum; i++)
{
delete heapArray[i];
heapArray[i] = NULL;
}
}
if (NULL != heapArray)
{
delete[] heapArray;
heapArray = NULL;
}
elemNum = 0;
}
template <class T, unsigned int capacity>
bool Heap<T, capacity>::isEmpty()
{
bool result = false;
if (0 == elemNum)
{
result = true;
}
else
{
result = false;
}
return result;
}
template <class T, unsigned int capacity>
bool Heap<T, capacity>::isFull()
{
bool result = false;
if (capacity == elemNum)
{
result = true;
}
else
{
result = false;
}
return result;
}
template <class T, unsigned int capacity>
void Heap<T, capacity>::AddElem(T value)
{
if (isFull())
{
//Do nothing
}
else
{
HeapNode<T>* node = new HeapNode<T>();
node->data = value;
if (isEmpty())
{
heapArray[0] = node;
elemNum++;
}
else
{
heapArray[elemNum] = node;
int parentIndex = (elemNum - 1) / 2;
int childIndex = elemNum;
while (parentIndex >= 0) //has parent
{
bool hasSwap = false;
if (heapArray[childIndex]->data > heapArray[parentIndex]->data)
{
int temp = heapArray[parentIndex]->data;
heapArray[parentIndex]->data = heapArray[childIndex]->data;
heapArray[childIndex]->data = temp;
hasSwap = true;
}
if (!hasSwap)
{
break;
}
else
{
childIndex = parentIndex;
parentIndex = (parentIndex - 1) / 2;
}
}
elemNum++;
}
}
return;
}
template <class T, unsigned int capacity>
void Heap<T, capacity>::deleteElem(T& value)
{
if (isEmpty())
{
//Do nothing
}
else
{
value = heapArray[0]->data;
//Copy last value to root, delete last memory
heapArray[0]->data = heapArray[elemNum - 1]->data;
delete heapArray[elemNum - 1];
heapArray[elemNum - 1] = NULL;
elemNum--;
//move deap
int index = 0;
while (index * 2 + 1 < elemNum)
{
bool hasSwap = false;
if (index * 2 + 2 < elemNum) //Both has left and right
{
//compare 3 elem, index, index*2+1 & index*2+2
if (heapArray[index * 2 + 1]->data > heapArray[index * 2 + 2]->data) //Left is big
{
if (heapArray[index]->data < heapArray[index * 2 + 1]->data)
{
//swap
int temp = heapArray[index]->data;
heapArray[index]->data = heapArray[index * 2 + 1]->data;
heapArray[index * 2 + 1]->data = temp;
hasSwap = true;
index = index * 2 + 1;
}
else
{
break;
}
}
else //Right is big
{
if (heapArray[index]->data < heapArray[index * 2 + 2]->data)
{
//swap
int temp = heapArray[index]->data;
heapArray[index]->data = heapArray[index * 2 + 2]->data;
heapArray[index * 2 + 2]->data = temp;
hasSwap = true;
index = index * 2 + 2;
}
else
{
break;
}
}
}
else //only has left
{
//compare 2 elem, index & index*2+1, index*2+1 must leaf node, after compare, no need loop
if (heapArray[index]->data < heapArray[index * 2 + 1]->data)
{
int temp = heapArray[index]->data;
heapArray[index]->data = heapArray[index * 2 + 1]->data;
heapArray[index * 2 + 1]->data = temp;
break;
}
else
{
break;
}
}
if (!hasSwap)
{
break;
}
}
}
return;
}