#include <stdio.h> #include <stdlib.h> //二叉树的每一个节点 struct t_node{ int data; struct t_node *left; struct t_node *right; }; //创建一棵哈夫曼树 struct t_node* create_huffman_tree(int datas[], int n) { //用于创建n个二叉树节点 struct t_node **huff_elems; //树的根 struct t_node *p; //i,j做循环,m1,m2分别记录最小值和次小值下标 int i, m1, m2, j; //分配n个指针大小的空间 huff_elems = (struct t_node**)calloc(n, sizeof(struct t_node*)); //为每个指针分配空间,创建n个二叉树节点 for(i = 0; i < n; i++) { huff_elems[i] = (struct t_node*)malloc(sizeof(struct t_node)); huff_elems[i]->data = datas[i]; huff_elems[i]->left = huff_elems[i]->right = NULL; } //第一次会从所有元素里面找两个最小的,以后会从所有的元素和所有生成的子树中 //寻找最小的两个,所以循环n-1次即可以循环完毕 for(i = 0; i < n-1; i++) { m1 = -1; //每次将m1设置成指向第一个非空的元素或子树 //将m2设置成指向第二个非空的元素或子树 for(j = 0; j < n; j++) { if(huff_elems[j] != NULL && m1 == -1) { m1 = j; continue; } else if(huff_elems[j] != NULL) { m2 = j; break; } } //将m1指向最小的那个值,m2指向第二小的那个值 for(j = m2; j < n; j++) { if(huff_elems[j] != NULL && huff_elems[j]->data < huff_elems[m1]->data) { m2 = m1; m1 = j; } else if(huff_elems[j] != NULL && huff_elems[j]->data < huff_elems[m2]->data) { m2 = j; } } //利用两个最小的值组成一个新的节点,节点权为两个权之和 p = (struct t_node*)malloc(sizeof(struct t_node)); p->left = huff_elems[m1]; p->right = huff_elems[m2]; p->data = huff_elems[m1]->data + huff_elems[m2]->data; huff_elems[m1] = p; huff_elems[m2] = NULL; } //释放n个指针大小的空间 free(huff_elems); return p; } //打印哈夫曼树的权值 int calc_weight(struct t_node *tree, int len) { if(tree == NULL) return 0; else if(tree->left == NULL && tree->right == NULL) return tree->data*len; else return calc_weight(tree->left, len+1) + calc_weight(tree->right, len+1); } int main() { int test[] = {3, 9, 5, 12, 6, 15}; struct t_node *tree = create_huffman_tree(test, 6); printf("%d/n",calc_weight(tree, 0)); return 0; }
说来惭愧,觉得哈夫曼树挺简单的,但是自己写起来,写了半天都写不对,最后还是参考别人的才写出来的。接着写哈夫曼编码。
#include <stdio.h> #include <stdlib.h> //二叉树的每一个节点 struct t_node{ int data; struct t_node *left; struct t_node *right; }; //创建一棵哈夫曼树 struct t_node* create_huffman_tree(int datas[], int n) { //用于创建n个二叉树节点 struct t_node **huff_elems; //树的根 struct t_node *p; //i,j做循环,m1,m2分别记录最小值和次小值下标 int i, m1, m2, j; //分配n个指针大小的空间 huff_elems = (struct t_node**)calloc(n, sizeof(struct t_node*)); //为每个指针分配空间,创建n个二叉树节点 for(i = 0; i < n; i++) { huff_elems[i] = (struct t_node*)malloc(sizeof(struct t_node)); huff_elems[i]->data = datas[i]; huff_elems[i]->left = huff_elems[i]->right = NULL; } //第一次会从所有元素里面找两个最小的,以后会从所有的元素和所有生成的子树中 //寻找最小的两个,所以循环n-1次即可以循环完毕 for(i = 0; i < n-1; i++) { m1 = -1; //每次将m1设置成指向第一个非空的元素或子树 //将m2设置成指向第二个非空的元素或子树 for(j = 0; j < n; j++) { if(huff_elems[j] != NULL && m1 == -1) { m1 = j; continue; } else if(huff_elems[j] != NULL) { m2 = j; break; } } //将m1指向最小的那个值,m2指向第二小的那个值 for(j = m2; j < n; j++) { if(huff_elems[j] != NULL && huff_elems[j]->data < huff_elems[m1]->data) { m2 = m1; m1 = j; } else if(huff_elems[j] != NULL && huff_elems[j]->data < huff_elems[m2]->data) { m2 = j; } } //利用两个最小的值组成一个新的节点,节点权为两个权之和 p = (struct t_node*)malloc(sizeof(struct t_node)); p->left = huff_elems[m1]; p->right = huff_elems[m2]; p->data = huff_elems[m1]->data + huff_elems[m2]->data; huff_elems[m1] = p; huff_elems[m2] = NULL; } //释放n个指针大小的空间 free(huff_elems); return p; } //打印哈夫曼树的权值 int calc_weight(struct t_node *tree, int len) { if(tree == NULL) return 0; else if(tree->left == NULL && tree->right == NULL) return tree->data*len; else return calc_weight(tree->left, len+1) + calc_weight(tree->right, len+1); } //哈夫曼编码 void huff_coding(struct t_node *tree, int len) { int i; //用来记录路径的编码,二叉树深度不得超10 static int a[10]; if(tree != NULL) { //如果到达叶子节点,打印路径 if(tree->left == NULL && tree->right == NULL) { printf("%d的编码是:", tree->data); for(i = 0; i < len; i++) printf("%d ", a[i]); printf("/n"); } else { a[len] = 0; huff_coding(tree->left, len+1); a[len] = 1; huff_coding(tree->right, len+1); } } } int main() { int test[] = {1, 2, 3}; struct t_node *tree = create_huffman_tree(test, 3); printf("%d/n",calc_weight(tree, 0)); huff_coding(tree, 0); return 0; }