c语言哈夫曼树的构造及编码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
c语言哈夫曼树的构造及编码
一、哈夫曼树概述
哈夫曼树是一种特殊的二叉树,它的构建基于贪心算法。
它的主要应用是在数据压缩和编码中,可以将频率高的字符用较短的编码表示,从而减小数据存储和传输时所需的空间和时间。
二、哈夫曼树的构造
1. 哈夫曼树的定义
哈夫曼树是一棵带权路径长度最短的二叉树。
带权路径长度是指所有叶子节点到根节点之间路径长度与其权值乘积之和。
2. 构造步骤
(1) 将待编码字符按照出现频率从小到大排序。
(2) 取出两个权值最小的节点作为左右子节点,构建一棵新的二叉树。
(3) 将新构建的二叉树加入到原来排序后队列中。
(4) 重复上述步骤,直到队列只剩下一个节点,该节点即为哈夫曼树的根节点。
3. C语言代码实现
以下代码实现了一个简单版哈夫曼树构造函数:
```c
typedef struct TreeNode {
int weight; // 权重值
struct TreeNode *leftChild; // 左子节点指针
struct TreeNode *rightChild; // 右子节点指针
} TreeNode;
// 构造哈夫曼树函数
TreeNode* createHuffmanTree(int* weights, int n) {
// 根据权值数组构建节点队列,每个节点都是一棵单独的二叉树
TreeNode** nodes = (TreeNode**)malloc(sizeof(TreeNode*) * n);
for (int i = 0; i < n; i++) {
nodes[i] = (TreeNode*)malloc(sizeof(TreeNode));
nodes[i]->weight = weights[i];
nodes[i]->leftChild = NULL;
nodes[i]->rightChild = NULL;
}
// 构建哈夫曼树
while (n > 1) {
int minIndex1 = -1, minIndex2 = -1;
for (int i = 0; i < n; i++) {
if (nodes[i] != NULL) {
if (minIndex1 == -1 || nodes[i]->weight < nodes[minIndex1]->weight) {
minIndex2 = minIndex1;
minIndex1 = i;
} else if (minIndex2 == -1 || nodes[i]->weight < nodes[minIndex2]->weight) {
minIndex2 = i;
}
}
}
TreeNode* newNode =
(TreeNode*)malloc(sizeof(TreeNode));
newNode->weight = nodes[minIndex1]->weight + nodes[minIndex2]->weight;
newNode->leftChild = nodes[minIndex1];
newNode->rightChild = nodes[minIndex2];
// 将新构建的二叉树加入到原来排序后队列中
nodes[minIndex1] = newNode;
nodes[minIndex2] = NULL;
n--;
}
return nodes[minIndex1];
}
```
三、哈夫曼编码
1. 哈夫曼编码的定义
哈夫曼编码是一种前缀编码方式,它将每个字符的编码表示为二进制串。
哈夫曼编码的特点是没有任何一个字符的编码是另一个字符编码的前缀。
2. 编码步骤
(1) 构建哈夫曼树。
(2) 从根节点开始遍历哈夫曼树,当遇到左子节点时,在当前编码后加0;当遇到右子节点时,在当前编码后加1。
(3) 将每个字符的编码存储在一个表中。
3. C语言代码实现
以下代码实现了一个简单版哈夫曼编码函数:
```c
typedef struct HuffCode {
char ch; // 字符
char* code; // 编码串
} HuffCode;
// 递归遍历哈夫曼树,生成每个字符对应的哈夫曼编码
void generateHuffmanCode(TreeNode* root, char* code, int len, HuffCode* huffCodes, int* index) {
if (root == NULL) {
return;
}
if (root->leftChild == NULL && root->rightChild == NULL) { huffCodes[*index].ch = root->ch;
huffCodes[*index].code = (char*)malloc(sizeof(char) * len + 1);
strncpy(huffCodes[*index].code, code, len);
huffCodes[*index].code[len] = '\0';
(*index)++;
} else {
code[len] = '0';
generateHuffmanCode(root->leftChild, code, len + 1, huffCodes, index);
code[len] = '1';
generateHuffmanCode(root->rightChild, code, len + 1, huffCodes, index);
}
}
// 构造哈夫曼编码函数
void createHuffmanCode(TreeNode* root) {
char* code = (char*)malloc(sizeof(char) * 100);
HuffCode* huffCodes = (HuffCode*)malloc(sizeof(HuffCode) * 256);
int index = 0;
generateHuffmanCode(root, code, 0, huffCodes, &index);
// 输出每个字符对应的哈夫曼编码
for (int i = 0; i < index; i++) {
printf("%c: %s\n", huffCodes[i].ch, huffCodes[i].code);
}
}
```
四、总结
哈夫曼树和哈夫曼编码是数据压缩和编码中非常重要的算法。
通过构建哈夫曼树和生成哈夫曼编码,我们可以将频率高的字符用较短的编码表示,从而减小数据存储和传输时所需的空间和时间。
在实际应用中,我们需要根据具体的需求选择合适的算法,并进行相应的优化。