- 堆数据结构是一个完全二叉树,父结点值都大于子结点值(都小于子结点值)。
- 用数组表示堆(0,...,size-1),根节点的下标为0,对于任意一个结点i,其左子结点为2*i+1, 右子结点为2*i+2。
- 堆中最后一个非叶子结点的下标为size/2-1。
//例程中是建一个大头堆
template<typename T>
void adjustHeap(T data[], int start, int end)
{
//沿着子结点下顺
//start的左子结点为2*start+1,右子结点为2*start+2.
for (int i = 2 * start + 1; i < end; ++i)
{
if (i < end - 1 && data[i] < data[i + 1])//这里需要注意一下i+1会不会越界
{
++i;//让i指向子结点中的较大者
}
if (data[i] < data[start]) //满足堆性质,不用调整
{
break;
}
//最大子结点与父结点交换
T temp = data[start];
data[start] = data[i];
data[i] = temp;
start = i;//start下顺,接着调整
}
}
//将一个数组初始化为堆,从最后一个非叶子开始从下往上进行adjustHeap
template<typename T>
void buildHeap(T data[], int size)
{
for (int start = size / 2 - 1; start >= 0; --start)
{
adjustHeap(data, start, size);
}
}
template<typename T>
void heapSort(T data[], int size)
{
//对数组建堆
buildHeap(data, size);
//将堆的第一个元素与最后一个元素交换,然后adjustHeap
for (int i = size - 1; i > 0; --i)
{
T temp = data[0];
data[0] = data[i];
data[i] = temp;
adjustHeap(data, 0, i);
}
}
下面补充一个递归版的adjust_heap:
template<class T>
void adjust_heap(T heap[], int start, int end) //[start, end)
{
int left = 2 * start + 1, right = 2 * start + 2;
if (left < end)
{
int max_idx = left;
if (right < end)
{
if (heap[left] < heap[right])
{
max_idx = right;
}
}
if (heap[max_idx] <= heap[start])
{
return; //不用调整了,父节点最大
}
std::swap(heap[start], heap[max_idx]);
adjust_heap(heap, max_idx, end);
}
}