#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;
}