#pragma once
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct Heap {
int array[100];
int size;
} Heap;
void HeapInit(Heap *pH, int array[], int size)
{
assert(pH);
memcpy(pH->array, array, sizeof(int)* size);
pH->size = size;
}
void Swap(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
// 建大堆
void AdjustDownRecursion(Heap *pH, int parent)
{
// 判断是否是叶子结点
// 没有左孩子,没有右孩子
// 完全二叉树,没有左孩子,一定没有右孩子
// 有没有左孩子,判断左孩子的下标是否越界
int left = 2 * parent + 1;
int right = 2 * parent + 2;
int maxChild;
if (left >= pH->size) {
// 是叶子结点
return;
}
// 肯定有左孩子,右孩子可能有,可能没有
// 找出谁是大的孩子
maxChild = left;
if (right < pH->size && pH->array[right] > pH->array[left]) {
maxChild = right;
}
if (pH->array[parent] > pH->array[maxChild]) {
// 现在满足堆了
return;
}
Swap(pH->array + parent, &(pH->array[maxChild]));
AdjustDownRecursion(pH, maxChild);
}
// 建大堆
void AdjustDownLoop(Heap *pH, int parent)
{
while (1) {
// 判断是否是叶子结点
// 没有左孩子,没有右孩子
// 完全二叉树,没有左孩子,一定没有右孩子
// 有没有左孩子,判断左孩子的下标是否越界
int left = 2 * parent + 1;
int right = 2 * parent + 2;
int maxChild;
if (left >= pH->size) {
// 是叶子结点
return;
}
// 肯定有左孩子,右孩子可能有,可能没有
// 找出谁是大的孩子
maxChild = left;
if (right < pH->size && pH->array[right] > pH->array[left]) {
maxChild = right;
}
if (pH->array[parent] > pH->array[maxChild]) {
// 现在满足堆了
return;
}
Swap(pH->array + parent, &(pH->array[maxChild]));
parent = maxChild;
//AdjustDownRecursion(pH, maxChild);
}
}
void HeapMake(Heap *pH)
{
int i;
for (i = (pH->size - 2) / 2; i >= 0; i--) {
AdjustDownLoop(pH, i);
}
}
int HeapTop(Heap *pH)
{
return pH->array[0];
}
int HeapSize(Heap *pH)
{
return pH->size;
}
int HeapIsEmpty(Heap *pH)
{
return pH->size == 0 ? 1 : 0;
}
void HeapPop(Heap *pH)
{
assert(pH);
assert(pH->size > 0);
pH->array[0] = pH->array[pH->size - 1];
pH->size--;
AdjustDownLoop(pH, 0);
}
void AdjustUp(Heap *pH, int child)
{
int parent;
while (1) {
// (0 - 1) / 2 = 0
parent = (child - 1) / 2;
if (child == 0) {
// 走到整棵树的根了
break;
}
if (pH->array[parent] >= pH->array[child]) {
// 满足堆了
break;
}
Swap(pH->array + parent, pH->array + child);
child = parent;
}
}
void HeapInsert(Heap *pH, int data)
{
pH->array[pH->size++] = data;
AdjustUp(pH, pH->size - 1);
}
// 大堆
void AdjustDownArray(int array[], int size, int root)
{
int parent = root;
int left, right, max;
while (1) {
left = parent * 2 + 1;
right = parent * 2 + 2;
if (left >= size) {
return;
}
max = left;
if (right < size && array[right] > array[left]) {
max = right;
}
if (array[parent] >= array[max]) {
return;
}
Swap(array + parent, array + max);
parent = max;
}
}
// 在 array 中找到最小的 k 个数
int * TopK(int array[], int size, int k)
{
int i;
int *rarray = (int *)malloc(sizeof(int)* k);
for (i = 0; i < k; i++) {
rarray[i] = array[i];
}
// 建堆 (rarray)
for (i = (k - 2) / 2; i >= 0; i--) {
AdjustDownArray(rarray, k, i);
}
for (i = k; i < size; i++) {
if (array[i] < rarray[0]) {
rarray[0] = array[i];
// 对 rarray 进行向下调整
AdjustDownArray(rarray, k, 0);
}
}
return rarray;
}
void HeapSortRight(int array[], int size)
{
int i;
for (i = size / 2 - 1; i >= 0; i--) {
AdjustDownArray(array, size, i);
}
for (i = 0; i < size) {
Swap(&(array[0]), &(array[size - 1 - i]));
AdjustDownArray(array, size - 1 - i, 0);
}
}
void HeapSortWrong(int array[], int size)
{
int i, j;
for (j = 0; j < size; j++) {
for (i = (size -j) / 2 - 1; i >= j; i--) {
AdjustDownArray(array + j, size - j, i); // 假设小堆
}
}
}
void Test()
{
Heap heap;
int array[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
int size = sizeof(array) / sizeof(int);
HeapInit(&heap, array, size);
HeapMake(&heap);
for (int i = 0; i < heap.size; i++) {
printf("%d ", heap.array[i]);
}
printf("\n");
printf("Heap\n");
}