最大堆的C语言实现(参考CLRS)

最大堆的实现代码(保存在文件My_max_heap.h中)

/*
 * @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

你可能感兴趣的:(算法学习,最大堆,CLRS,C语言)