数据结构与C 知识量:8 - 24 - 99
哈夫曼树(Huffman Tree),又称最优二叉树,是一种带权路径长度最短的树。树的路径长度:从树根到树中每一个节点的路径长度之和。结点之间的路径长度:从一个结点到另一个结点之间的分支数目。结点的带权路径长度:从该结点到树根之间的路径长度与节点上权的乘积。树的带权路径长度:Weighted Path Length of Tree,简称为WPL,树中所有叶子结点的带权路径长度之和,记作: WPL最小的二叉树就称作最有二叉树或哈夫曼树。
哈夫曼树的构造过程如下:
给定n个带有权值的结点,组成一个结点集合M;
从集合M中选出权值最小的两个结点A,B,权值分别为,构造一棵二叉树T,T的根结点C权值为;
删除结点A、B,将结点C加入到集合M中;
重复步骤2和3,直至M中只剩下一个结点为止。
哈夫曼树是一种优化后的二叉树结构,它在数据压缩等领域有广泛的应用。
以下是使用C语言实现哈夫曼树的构造算法的示例代码:
#include <stdio.h> #include <stdlib.h> // 定义二叉树结构体 struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; // 定义比较函数,用于选取权值最小的两棵树 int cmp(const void *a, const void *b) { return (*(struct TreeNode*)a)->val - (*(struct TreeNode*)b)->val; } // 构造哈夫曼树 struct TreeNode* buildHuffmanTree(int weights[], int n) { // 构造n棵二叉树的森林 struct TreeNode **trees = (struct TreeNode**)malloc(n * sizeof(struct TreeNode*)); for (int i = 0; i < n; i++) { trees[i] = (struct TreeNode*)malloc(sizeof(struct TreeNode)); trees[i]->val = weights[i]; trees[i]->left = NULL; trees[i]->right = NULL; } // 选取权值最小的两棵树,构造新的二叉树,并更新森林 while (n > 1) { int *temp = (int*)malloc(2 * sizeof(int)); for (int i = 0; i < 2; i++) { temp[i] = trees[i]->val; } qsort(temp, 2, sizeof(int), cmp); struct TreeNode *newTree = (struct TreeNode*)malloc(sizeof(struct TreeNode)); newTree->val = temp[0] + temp[1]; newTree->left = trees[temp[0]]; newTree->right = trees[temp[1]]; trees[temp[0]] = NULL; trees[temp[1]] = NULL; n--; trees = (struct TreeNode**)realloc(trees, n * sizeof(struct TreeNode*)); trees[n] = newTree; } // 返回哈夫曼树的根节点 return trees[0]; }
哈夫曼编码(Huffman Coding)是一种可变长度编码方法,它根据字符出现的概率来构造异字头的平均长度最短的码字。哈夫曼编码是一种前缀编码,即没有任何字符的编码是其他字符编码的前缀。
哈夫曼编码的原理是:首先,将待编码的字符按照其出现的概率由大到小排序;然后,从概率最小的两个字符开始,可选其中一个支路为0,另一支路为1,将已编码的两支路的概率合并,并重新排队;接着,重复上述步骤,直到合并概率归一时为止。这样得到的码字即为哈夫曼编码。
哈夫曼编码是一种高效的编码方法,其编码长度接近于最佳编码长度。在实际应用中,哈夫曼编码被广泛应用于数据压缩等领域。
以下是使用C语言实现哈夫曼编码的算法示例:
#include <stdio.h> #include <stdlib.h> // 定义二叉树结构体 struct TreeNode { int val; int freq; struct TreeNode *left; struct TreeNode *right; }; // 构造二叉树 struct TreeNode* createTreeNode(int val, int freq) { struct TreeNode *node = (struct TreeNode*)malloc(sizeof(struct TreeNode)); node->val = val; node->freq = freq; node->left = NULL; node->right = NULL; return node; } // 构建哈夫曼树 struct TreeNode* buildHuffmanTree(int weights[], int n) { // 构造n棵二叉树的森林 struct TreeNode **trees = (struct TreeNode**)malloc(n * sizeof(struct TreeNode*)); for (int i = 0; i < n; i++) { trees[i] = createTreeNode(weights[i], 1); } // 选取权值最小的两棵树,构造新的二叉树,并更新森林 while (n > 1) { struct TreeNode **temp = (struct TreeNode**)malloc(2 * sizeof(struct TreeNode*)); temp[0] = trees[0]; temp[1] = trees[1]; int freq[2] = {temp[0]->freq, temp[1]->freq}; qsort(temp, 2, sizeof(struct TreeNode*), (int(*)(const void*, const void*))cmp); qsort(freq, 2, sizeof(int), cmp); struct TreeNode *newTree = createTreeNode(freq[0] + freq[1], 0); newTree->left = temp[0]; newTree->right = temp[1]; trees[0] = NULL; trees[1] = NULL; n--; trees = (struct TreeNode**)realloc(trees, n * sizeof(struct TreeNode*)); trees[n] = newTree; } // 返回哈夫曼树的根节点 return trees[0]; } // 比较函数,用于选取权值最小的两棵树 int cmp(const void *a, const void *b) { return ((struct TreeNode*)a)->freq - ((struct TreeNode*)b)->freq; } // 打印哈夫曼编码树(前序遍历) void printHuffmanTree(struct TreeNode *root, int depth) { if (root == NULL) { return; } for (int i = 0; i < depth; i++) { printf("\t"); } printf("%d(%d)\n", root->val, root->freq); printHuffmanTree(root->left, depth + 1); printHuffmanTree(root->right, depth + 1); }
Copyright © 2017-Now pnotes.cn. All Rights Reserved.
编程学习笔记 保留所有权利
MARK:3.0.0.20240214.P35
From 2017.2.6