什么是堆
简单来说,堆就是一棵特殊的二叉树,特殊在哪里呢,有两点:
- 堆总是一棵完全二叉树(树的1~n层是一个满二叉树,最后一层的节点全部靠左)
- 所有的子都比父小(大根堆)或者所有的子都比父大(小根堆)
几个概念需要了解一下
- 1~12是13的子;10、9、6、5、4、3是12的子。。。
- 12和11是兄弟;10、9是兄弟;10和8不是兄弟。。。
- 除了2可以没有兄弟,其他所有节点都必须要有兄弟
如何创建堆
给你一个数组,怎么把这个数组内的树变成一个堆。
1.定义一个堆结构体
struct Heap {
int* arr; //最后这个堆内存储的其实还是一个数组,但是我们自己把数组画成完全二叉树
int size;
}
2.创建堆
Heap hp; //这个时候这个堆还是空的
3.给定一个数组
int orignArry[8]={53,17,78,9,45,65,87,32};
int len = orignArry.size();
//把数组所代表的二叉树赋给堆(其实这个时候还不是堆)
hp->arr = orignArry;
hp->size = len;
有没有人跟我一样,以为直接把数组变成一个堆。
那不是很简单嘛,排个序,然后从大到小画个二叉树,就解决了。
其实,他们的意思应该是这个数组一上来就代表了一个完全二叉树。
4.把hp变成真正的堆(排序)
void buildHeap(Heap& heap)
{
for (int i = (heap.size - 1) / 2; i >= 0; i--) {
adjustDown(heap, i);
}
}
void adjustDown(Heap& heap, int index)
{
int cur = heap.arr[index];
int parent, child;
for (parent = index; (parent * 2 + 1) < heap.size; parent = child) {
child = parent * 2 + 1;
if (((child + 1) < heap.size) && (heap.arr[child + 1] > heap.arr[child]))
{
child++;
}
if (cur >= heap.arr[child])
break;
else
{
heap.arr[parent] = heap.arr[child];
heap.arr[child] = cur;
}
}
buildHeap(hp); //从此之后,hp就是一个真正的堆了