【算法概论】Huffman树

1、哈夫曼树,又叫最优二叉树:效率最高的判决数。

2、回忆树的相关知识

① 路径长度:路径上的结点数 - 1。

② 结点的权:在许多应用中,常常给树的结点赋予一个有意义的数,称为该结点的权。

③ 结点的带权路径长度:该结点到树根的路径长度 × 该结点的权。

④ 树的带权路径长度:树上所有叶子结点的带权路径长度之和,通常记作 WPL 。

3、哈夫曼树定义

       在权为w1, w2, …, wn的 n 个叶子结点的所有二叉树中,带权路径长度 WPL 最小的二叉树称为赫夫曼树或最优二叉树。

4、哈夫曼树的构造(哈夫曼算法)

       ① 根据给定的 n 个权值 { w1, w2, … , wn } 构成二叉树集合 F = { T1, T2, … , Tn },其中每棵二叉树 Ti 中只有一个带权为 wi 的根结点,其左右子树为空。

       ② 在 F 中选取两棵根结点权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为左右子树根结点的权值之和。

       ③ 在 F 中删除这两棵树,同时将新的二叉树加入 F 中。

       ④ 重复2、3,直到 F 只含有一棵树为止。(得到哈夫曼树)

5、关于哈夫曼树的注意点

       ① 满二叉树不一定是哈夫曼树;

       ② 哈夫曼树中权越大的叶子离根越近(很好理解,WPL最小的二叉树);

       ③ 具有相同带权结点的哈夫曼树不惟一;

       ④ 哈夫曼树的结点的度数为 0 或 2, 没有度为 1 的结点;

       ⑥ 包含 n 个叶子结点的哈夫曼树中共有 2n – 1 个结点;

       ⑦ 包含 n 棵树的森林要经过 n–1 次合并才能形成哈夫曼树,共产生 n–1 个新结点。

 

参考:哈夫曼(huffman)树和哈夫曼编码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是用C语言实现构建Huffman算法的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_SIZE 1000 // 定义Huffman节点结构体 typedef struct { int weight; // 权值 int parent; // 父节点下标 int left; // 左子节点下标 int right; // 右子节点下标 } HuffNode, *HuffTree; // 定义Huffman编码结构体 typedef struct { char ch; // 字符 char code[MAX_SIZE]; // 编码 } HuffCode, *HuffCodeTable; // 选择权值最小的两个节点 void select(HuffTree tree, int n, int *s1, int *s2) { int i; int min1, min2; min1 = min2 = MAX_SIZE; // 找出第一个权值最小的节点 for (i = 0; i < n; i++) { if (tree[i].weight < min1 && tree[i].parent == -1) { min1 = tree[i].weight; *s1 = i; } } // 找出第二个权值最小的节点 for (i = 0; i < n; i++) { if (tree[i].weight < min2 && tree[i].parent == -1 && i != *s1) { min2 = tree[i].weight; *s2 = i; } } } // 构建Huffman void buildHuffTree(HuffTree tree, int n) { if (n <= 1) return; int i, s1, s2; for (i = 0; i < 2 * n - 1; i++) { tree[i].parent = -1; tree[i].left = -1; tree[i].right = -1; } // 构建n-1个节点的Huffman for (i = n; i < 2 * n - 1; i++) { select(tree, i, &s1, &s2); tree[s1].parent = i; tree[s2].parent = i; tree[i].left = s1; tree[i].right = s2; tree[i].weight = tree[s1].weight + tree[s2].weight; } } // 获取Huffman编码 void getHuffCode(HuffTree tree, HuffCodeTable table, int n) { int i, j; char *code = (char *)malloc(n * sizeof(char)); code[n - 1] = '\0'; for (i = 0; i < n; i++) { int start = n - 1; int c = i; int p = tree[c].parent; while (p != -1) { if (tree[p].left == c) { code[--start] = '0'; } else { code[--start] = '1'; } c = p; p = tree[c].parent; } strcpy(table[i].code, &code[start]); } free(code); } int main() { int n; printf("输入字符个数:"); scanf("%d", &n); // 输入字符及其权值 HuffTree tree = (HuffTree)malloc(sizeof(HuffNode) * (2 * n - 1)); HuffCodeTable table = (HuffCodeTable)malloc(sizeof(HuffCode) * n); int i; for (i = 0; i < n; i++) { printf("输入第%d个字符及其权值:", i + 1); scanf("%s %d", &table[i].ch, &tree[i].weight); } // 构建Huffman buildHuffTree(tree, n); // 获取Huffman编码 getHuffCode(tree, table, n); // 输出Huffman编码 printf("Huffman编码如下:\n"); for (i = 0; i < n; i++) { printf("%c: %s\n", table[i].ch, table[i].code); } free(tree); free(table); return 0; } ``` 这段代码实现了从用户输入字符及其权值,构建Huffman,获取Huffman编码,输出Huffman编码的功能。在构建Huffman时,采用的是贪心策略,每次选择权值最小的两个节点进行合并。在获取Huffman编码时,采用的是自底向上的遍历方式,从叶子节点到根节点依次获取每个字符的编码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值