我要理解二叉树如何定义一个堆的
- 必须是一颗完全二叉树
- 我们可以分大堆和小堆
- 这里主要通过顺序链表的方法定义堆
-
这是一个从上往下的大堆
-
我们要如何存储这个堆了,显然我们需要一个数组,然后通过写算法实现这个堆的顺序存储。
-
这里主要说一下堆的升序与降序,以及初始化,插入删除吧。
-
堆其实理解起来相比二叉树的链式存储要容易很多,堆升序时候我们其实主要需要的这是一个判断条件结点是否存在
以及二叉树的一个基本关系式,parent = child * 2 + 1 || parent = child * 2 + 2 -
好了还是看代码吧,短时间这个我也不知道怎么说了
#include <stddef.h>
#include <stdio.h>
#include <assert.h>
typedef struct Heap
{
int array[100];
int size;
} Heap;
static void Swap(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
void HeapInit(Heap *pH, int source[], int size)
{
for (int i = 0; i < size; i++) {
pH->array[i] = source[i];
}
pH->size = size;
}
void HeapAdjustDown(Heap *pH, int root)
{
int parent = root;
while (1) {
// 先判断有没有孩子(叶子结点)
// 数组角度去想 -> 孩子的下标是否越界
// 只要判断左孩子的下标(因为是完全二叉树)
int left = parent * 2 + 1;
if (left >= pH->size) {
// 越界,没有左孩子,也肯定没有右孩子
return;
}
// 一定有左孩子
int maxChild = left;
if (2 * parent + 2 < pH->size && pH->array[2 * parent + 2] > pH->array[left]) {
// 前一个条件是判断右孩子有没有
// 后一个条件判读是右孩子是否比左孩子大
maxChild = 2 * parent + 2;
}
if (pH->array[parent] > pH->array[maxChild]) {
return;
}
// 交换 root 和 maxChild 下标所在的值
int t = pH->array[parent];
pH->array[parent] = pH->array[maxChild];
pH->array[maxChild] = t;
parent = maxChild;
}
}
// 1. 数组的越界判断不对, 是否 == size
// 2. array[left] == NULL array -> int[] 这么判断左孩子在不在是错的
// 3. 交换的时候,交换的下标,而不是下标所在的值
void HeapAdjustDown2(Heap *pH, size_t root)
{
size_t parent = root;
size_t left, right;
size_t maxChild;
left = 2 * root + 1;
right = 2 * root + 2;
while (left < (size_t)pH->size) {
maxChild = left;
if (right < (size_t)pH->size && pH->array[left] < pH->array[right]) {
maxChild = right;
}
if (pH->array[maxChild] < pH->array[parent]) {
break;
}
Swap(pH->array + maxChild, pH->array + parent);
parent = maxChild;
left = 2 * parent + 1;
right = 2 * parent + 2;
}
// left 不存在
}
// i-- 写成 i++
void HeapMakeHeap(Heap *pH)
{
// [(size - 2) / 2, 0]
// 理解循环的区间的来历
for (int i = (pH->size - 2) / 2; i >= 0; i--) {
HeapAdjustDown(pH, i);
}
}
void HeapPop(Heap *pH)
{
pH->array[0] = pH->array[pH->size - 1];
pH->size--;
HeapAdjustDown(pH, 0);
}
int HeapTop(const Heap *pH)
{
return pH->array[0];
}
void HeapAdjustUp(Heap *pH, int child)
{
int parent;
while (child > 0) {
parent = (child - 1) / 2;
if (pH->array[parent] >= pH->array[child]) {
return;
}
Swap(pH->array + parent, pH->array + child);
child = parent;
}
}
void HeapPush(Heap *pH, int data)
{
assert(pH->size < 100);
pH->array[pH->size++] = data;
HeapAdjustUp(pH, pH->size - 1);
}
#include <stdio.h>
void Test()
{
int array[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
int size = sizeof(array) / sizeof(int);
Heap heap;
HeapInit(&heap, array, size);
HeapMakeHeap(&heap);
HeapPush(&heap, 100);
printf("%d\n", HeapTop(&heap));
printf("建堆完成\n");
}
int main()
{
Test();
return 0;
}
我们初始化放入的数据是 int array[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
我们看一下我们分别降序升序以后队中元素的变化吧
- 降序以后
- 我们插入100升序以后
- 好了,大概就这样了。