#include<stdio.h>node
#include<stdlib.h>数组
struct HaTree {函数
int weight; HaTree *left; HaTree *right;
};ui
struct MinHeap {code
//data表明HaTree的数组,也就是数组,只不过动态指定大小的 //size记录当前堆的元素个数 //capacity 记录堆的最大容量, HaTree *data; int size; int capacity;
};ci
//最小堆的初始化it
MinHeap* createMinHeap(int capacity) {io
MinHeap * h = (MinHeap *)malloc(sizeof(MinHeap)); h->data = (HaTree *)malloc((capacity + 1) * sizeof(HaTree)); h->size = 0; h->capacity = capacity; h->data[0].weight = -100000; h->data[0].left = NULL; h->data[0].right = NULL; return h;
}遍历
//最小堆插入元素,这个是为了提供当构造哈夫曼数产生新的节点时要插入最小堆使用的插入函数数据
void insertMinHeap(MinHeap *head, HaTree *T) {
//判断该堆是否满了 if (head->size == head->capacity) { printf("该最小堆已经满了\n"); return; } int i = head->size; //表示添加了一个元素 i++; head->size++; for (; head->data[i / 2].weight > T->weight; i = i / 2) { head->data[i].weight = head->data[i / 2].weight; head->data[i].left = head->data[i / 2].left; head->data[i].right = head->data[i / 2].right; } //新插入的节点一定有左右子树,因此不为空 head->data[i].weight = T->weight; head->data[i].left = T->left; head->data[i].right = T->right;
}
// 最小堆插入元素(我的没有采用另一种方式,先把数据插入到堆中,而后进行调整)
//我的采用的每次插入一个元素后,此时已是最小堆啦 ,这种方式比较浪费时间,可是容易理解
void init_insert_heap(MinHeap *head, int w) {
//判断该堆是否满了 if (head->size == head->capacity) { printf("该最小堆已经满了\n"); return; } int i = head->size; //表示添加了一个元素 i++; head->size++; for (; head->data[i / 2].weight > w; i = i / 2) { head->data[i].weight = head->data[i / 2].weight; } //这个地方为啥要把左右子树为空,由于这些点最终都哈夫曼树的叶子节点,左右子树都空 head->data[i].weight = w; head->data[i].left = NULL; head->data[i].right = NULL;
}
//删除最小堆中的最小元素
HaTree * delete_min(MinHeap *head) {
if (head->size == 0) { printf("最小堆已经空了,请检查下你的操做\n"); return NULL; } HaTree *node = (HaTree *)malloc(sizeof(HaTree)); node->weight = head->data[1].weight; node->left = head->data[1].left; node->right = head->data[1].right; int parent, child = 0; //这么写的目的为了好理解 int temp = head->data[head->size].weight; head->size--; for (parent = 1; parent * 2 <= head->size; parent = child) { child = parent * 2; if (child != head->size && (head->data[child + 1].weight < head->data[child].weight)) child++; if (head->data[child].weight > temp) break; else { head->data[parent].weight = head->data[child].weight; head->data[parent].left = head->data[child].left; head->data[parent].right = head->data[child].right; } } head->data[parent].weight = temp; //注意理解head->size+1 和head->size++ head->data[parent].left = head->data[head->size + 1].left; head->data[parent].right = head->data[head->size + 1].right; //返回取出的最小堆的节点 return node;
}
//创建哈夫曼树
HaTree * buildTree(MinHeap *head) {
HaTree *ha = NULL; //最后一个直接从最小堆中取出,因此注意判断的条件 while (head->size>1) { ha = (HaTree *)malloc(sizeof(HaTree)); ha->left = delete_min(head); ha->right = delete_min(head); ha->weight = ha->left->weight + ha->right->weight; insertMinHeap(head, ha); } ha = delete_min(head); return ha;
}
//遍历下哈夫曼树,先序遍历
void preOrder(HaTree *p) {
if (p) { printf("%d\n", p->weight); preOrder(p->left); preOrder(p->right); }
}
int main() {
MinHeap * head = createMinHeap(20); int a[] = { 1,3,4,5 }; int length = sizeof(a) / sizeof(a[0]); //对哈夫曼树的进行权重的初始化 for (int i = 0; i < length; i++) { init_insert_heap(head, a[i]); } HaTree *p = buildTree(head); preOrder(p); printf("hello"); system("pause"); return 0;
}