/*
* @Description: 最大堆
* @Author: Fishermanykx
* @Date: 2019-09-25 20:35:28
* @LastEditors: Fishermanykx
* @LastEditTime: 2019-09-28 20:45:18
*/
#ifndef MY_MAX_HEAP
#define MY_MAX_HEAP
#include
#include
#include
#define ORIGINAL_ARRAY_SIZE 1
#define PARENT(node_index) \
(((node_index) % 2) ? ((node_index) / 2) : ((node_index) / 2 - 1))
#define LEFT_CHILD(node_index) (2 * (node_index) + 1)
#define RIGHT_CHILD(node_index) (2 * (node_index) + 2)
struct node {
int key;
};
typedef struct node Node;
typedef Node* ElemType;
int array_size = ORIGINAL_ARRAY_SIZE; // 用于存储堆的数组的规模
void MySwap(ElemType a, ElemType b);
ElemType* ExpandSize(ElemType a[], int* size);
ElemType GetNewNode(int key, double coeff);
bool IsEmpty(ElemType a[], const int heap_size);
void MaxHeapify(ElemType a[], int node_index, const int heap_size);
void BuildMaxHeap(ElemType a[], int heap_size);
void MyHeapSort(ElemType a[], int heap_size);
ElemType* HeapInsertNode(ElemType a[], ElemType new_elem, int* heap_size);
ElemType* HeapRemoveNode(ElemType a[], int node_index, int* heap_size);
ElemType GetMaxNode(ElemType a[]);
ElemType* ExtractMax(ElemType a[], int* heap_size);
void IncreaseKey(ElemType a[], int node_index, int key, const int heap_size);
void PrintHeap(ElemType* arr, const int heap_size);
/**
* @description: 交换堆中两结点a和b
* @param {type}
* a {ElemType }: 结点a
* b {ElemType }: 结点b
* @return: void
*/
void MySwap(ElemType a, ElemType b) {
ElemType c = (ElemType)malloc(sizeof(Node));
*c = *a;
*a = *b;
*b = *c;
free(c);
}
/**
* @description: 数组扩容
* @param {type}
* a[] {Array, elem type: ElemType} : heap
* size {int *} : 指向原先数组的规模的指针
* @return: 指向扩容后数组的指针
*/
ElemType* ExpandSize(ElemType a[], int* size) {
a = (ElemType*)realloc(a, 2 * *size * sizeof(ElemType));
*size = 2 * *size;
return a;
}
/**
* @description: 判断堆是否为空
* @param {type}
* a {ElemType *}: 存储堆的数组
* heap_size {const int}: 堆内元素的个数
* @return: 为空返回true, 否则返回false
*/
bool IsEmpty(ElemType a[], const int heap_size) {
return (heap_size == 0) ? true : false;
}
/**
* @description: 生成一个新结点
* @param {type}
* key {int}: 新结点的键值
* @return: 新结点
*/
ElemType GetNewNode(int key, double coeff) {
ElemType new_node = (ElemType)malloc(sizeof(Node));
new_node->key = key;
new_node->coeff = coeff;
return new_node;
}
/**
* @description: 将以a[node_index]为根结点的堆转化为最大堆
* @param {type}
* a {ElemType }: 用来模拟堆的数组
* node_index {int}: 当前结点对应的下标
* heap_size {const int}: 当前堆的大小
* @return: void
*/
void MaxHeapify(ElemType a[], int node_index, const int heap_size) {
int left_child = LEFT_CHILD(node_index);
int right_child = RIGHT_CHILD(node_index);
int largest_index = node_index;
if (left_child < heap_size && a[left_child]->key > a[node_index]->key) {
largest_index = left_child;
}
if (right_child < heap_size && a[right_child]->key > a[largest_index]->key) {
largest_index = right_child;
}
if (largest_index != node_index) {
MySwap(a[largest_index], a[node_index]);
MaxHeapify(a, largest_index, heap_size);
}
}
/**
* @description: 构建最大堆
* @param {type}
* a[] {Array, elem type: Node*} : 用于模拟堆的数组
* heap_size {int} : 堆的大小
* @return: void
*/
void BuildMaxHeap(ElemType a[], int heap_size) {
for (int i = heap_size / 2 - 1; i >= 0; --i) {
MaxHeapify(a, i, heap_size);
}
}
/**
* @description: 堆排序(升序排序)
* @param {type}
* a[] {Array, elem type: Node*} : 用于模拟堆的数组
* heap_size {int}: 堆的大小
* @return: void
*/
void MyHeapSort(ElemType a[], int heap_size) {
BuildMaxHeap(a, heap_size);
for (int index = heap_size - 1; index > 0; --index) {
MySwap(a[0], a[index]);
--heap_size;
MaxHeapify(a, 0, heap_size);
}
}
/**
* @description: 向最大堆中插入一个新结点,并返回修改后的堆
* @param {type}
* a[] {Array, elem type: ElemType }: 存储堆的数组
* new_elem {ElemType}: 待插入的新结点
* heap_size {int *}: 指向原先堆的规模的指针
* @return: 修改后指向存储堆的数组的指针
*/
ElemType* HeapInsertNode(ElemType a[], ElemType new_elem, int* heap_size) {
if (*heap_size == array_size) { // 判断插入结点后是否会造成数组溢出
a = ExpandSize(a, &array_size);
}
a[*heap_size] = new_elem;
++(*heap_size);
IncreaseKey(a, *heap_size - 1, new_elem->key, *heap_size);
return a;
}
/**
* @description: 删除最大堆中下标为node_index的结点,并返回修改后的堆
* @param {type}
* a[] {Array, elem type: ElemType }: 存储堆的数组
* node_index {int}: 待删除的结点
* heap_size {int *}: 指向原先堆的规模的指针
* @return: 修改后指向存储堆的数组的指针
*/
ElemType* HeapRemoveNode(ElemType a[], int node_index, int* heap_size) {
MySwap(a[node_index], a[*heap_size - 1]);
--(*heap_size);
for (int i = *heap_size / 2 - 1; i >= 0; --i) MaxHeapify(a, i, *heap_size);
return a;
}
/**
* @description: 获取最大堆中存储最大键值的结点
* @param {type}
* a[] {Array, elem type: ElemType }: 存储堆的数组
* @return: max_node{ElemType }:存储最大值的结点
*/
ElemType GetMaxNode(ElemType a[]) { return a[0]; }
/**
* @description: 删除最大堆中存储最大值的结点,并返回修改后的堆
* @param {type}
* a[] {Array, elem type: ElemType }: 存储堆的数组
* heap_size {int *}: 指向原先堆的规模的指针
* @return: 修改后指向存储堆的数组的指针
*/
ElemType* ExtractMax(ElemType a[], int* heap_size) {
if (*heap_size < 1) {
printf("Heap underflow!\n");
exit(1);
}
return HeapRemoveNode(a, 0, heap_size);
}
/**
* @description: 将最大堆中a[node_index]对应结点的键值增加到key
* @param {type}
* a[] {Array, elem type: ElemType }: 存储堆的数组
* node_index {int}: 待增加键值的结点的下标
* key {int}: 修改后的键值
* heap_size {const int}: 堆的大小
* @return: void
*/
void IncreaseKey(ElemType a[], int node_index, int key, const int heap_size) {
if (key < a[node_index]->key) {
printf("Error! New key is smaller than the current key!\n");
exit(1);
}
a[node_index]->key = key;
while (node_index > 0 && a[PARENT(node_index)]->key < a[node_index]->key) {
MySwap(a[node_index], a[PARENT(node_index)]);
node_index = PARENT(node_index);
}
}
/**
* @description: 输出存储堆的数组
* @param {type}
* a {ElemType *}: 存储堆的数组
* heap_size {const int}: 堆的规模
* @return: void
*/
void PrintHeap(ElemType* a, const int heap_size) {
// printf("the heap is: ");
for (int i = 0; i < heap_size; ++i) {
printf("%d\t", a[i]->key);
printf("coeff :%lf\n", a[i]->coeff);
}
printf("\n");
}
#endif
#include "My_max_heap.h"
// test all the functions
int main(void) {
// 读入数据
int val, cnt = 0, heap_size = 0;
ElemType* arr;
arr = (ElemType*)malloc(sizeof(ElemType) * ORIGINAL_ARRAY_SIZE);
freopen("test.txt", "r", stdin);
// Read in the data
// test the function "HeapInsertNode" and "GetNewNode"
while (scanf("%d", &val) != EOF) {
ElemType new_elem = GetNewNode(val);
arr = HeapInsertNode(arr, new_elem, &heap_size);
}
// test the function "BuildMaxHeap"
BuildMaxHeap(arr, heap_size);
PrintHeap(arr, heap_size);
// test the function "HeapSort"
MyHeapSort(arr, heap_size);
printf("After heapsort\n");
PrintHeap(arr, heap_size);
// test the function "HeapRemoveNode"
arr = HeapRemoveNode(arr, 1, &heap_size);
printf("After deleting the second node, ");
PrintHeap(arr, heap_size);
printf("Size of the heap is: %d\n", heap_size);
// test the function "GetMaxNode"
ElemType max_node = GetMaxNode(arr);
printf("The value of the max node is: %d\n", max_node->key);
// test the function "ExtractMax"
for (int i = 0; i < 2; ++i) {
arr = ExtractMax(arr, &heap_size);
printf("After extracting the max node, ");
PrintHeap(arr, heap_size);
printf("Size of the heap is: %d\n", heap_size);
}
// test the function "IncreaseKey" and "IsEmpty"
if (!IsEmpty(arr, heap_size)) {
IncreaseKey(arr, 2, 6, heap_size);
printf("After the key of the third node is increased, ");
PrintHeap(arr, heap_size);
}
return 0;
}
3 2 4 5 1 6
the heap is: 6 4 5 2 1 3
After heapsort
the heap is: 1 2 3 4 5 6
After deleting the second node, the heap is: 6 5 3 4 1
Size of the heap is: 5
The value of the max node is: 6
After extracting the max node, the heap is: 5 4 3 1
Size of the heap is: 4
After extracting the max node, the heap is: 4 1 3
Size of the heap is: 3
After the key of the third node is increased, the heap is: 6 1 4
[Done] exited with code=0 in 0.28 seconds
[1] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein, Introduction to Algorithms [M], Massachusetts Institute of Technology