7.8 赫夫曼树应用解析(跟结点到叶子求每个字符的赫夫曼编码)
来源:互联网 发布:java解压缩rar文件 编辑:程序博客网 时间:2024/06/05 18:20
其他部分同 7.7赫夫曼树应用解析(叶子到根逆向求每个字符的赫夫曼编码)的编码,只更改HuffmanCoding函数来实现:如下
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/************************************************************************/
// 求解赫夫曼编码
/************************************************************************/
void HuffmanTreeCoding(HuffmanTree &HT, HuffmanCode &HC, int* w, int n)
{ // w存放n个字符的权值(均>0), 构造赫夫曼树,求出n个字符的赫夫曼编码HC
if (n <= 1)
return;
int nNodes; // 总结点和
int nodeIndex; // 根结点序号
nNodes = 2 * n - 1;
HT = (HuffmanTree)malloc( sizeof(HTNode) * (nNodes+1) ); // 0号单元未用
HuffmanTree pTree;
pTree = HT+1;
for (nodeIndex=1; nodeIndex <= n; ++nodeIndex,++pTree, ++w)
{
pTree->weight = *w;
pTree->parent = 0;
pTree->lchild = 0;
pTree->rchild = 0;
}
for ( ; nodeIndex <= nNodes; ++nodeIndex, ++pTree)
(*pTree).parent = 0;
// 创建赫夫曼树
int minIndex1, minIndex2;
for (nodeIndex = n+1; nodeIndex <= nNodes; nodeIndex++) // 循环n-1次
{ // 在HT[1~nodeIndexs-1]中选择parent为0且weight最小的两个结点,其序号分别为minIndex1,minIndex2
Select(HT, nodeIndex-1, minIndex1, minIndex2);
HT[minIndex1].parent = HT[minIndex2].parent = nodeIndex;
HT[nodeIndex].lchild = minIndex1;
HT[nodeIndex].rchild = minIndex2;
HT[nodeIndex].weight = HT[minIndex1].weight + HT[minIndex2].weight;
}
HC = (HuffmanCode)malloc( (n+1)*sizeof(char*));
// 分配n个字符编码的头指针向量([0]不用)
char* codingSize;
codingSize = (char*)malloc(sizeof(char) * n); // 分配求编码的工作空间
unsigned int c, cdlen;
c = nNodes;
cdlen = 0;
for (int i=1; i <= nNodes; i++)
HT[i].weight = 0; // 遍历赫夫曼时用作结点标识
while (c)
{
if (HT[c].weight == 0)
{ // 向左
HT[c].weight = 1;
if (HT[c].lchild != 0)
{
c = HT[c].lchild;
codingSize[cdlen++] = '0';
}
else if (HT[c].rchild == 0)
{ // 登记叶子结点的字符编码
HC[c] = (char*)malloc((cdlen+1) * sizeof(char));
codingSize[cdlen] = '\0';
strcpy(HC[c], codingSize); // 复制编码(串)
}
}
else if (HT[c].weight == 1)
{ // 向右
HT[c].weight = 2;
if (HT[c].rchild != 0)
{
c = HT[c].rchild;
codingSize[cdlen++] = '1';
}
}
else
{ // HT[c].weight = 2, 退回
HT[c].weight = 0;
c = HT[c].parent;
--cdlen; // 退到父结点,编码长度减1
}
}
// // 从叶子到根逆向求每个字符的赫夫曼编码
// HC = (HuffmanCode)malloc( (n+1)*sizeof(char*));
//
// // 分配n个字符编码的头指针向量([0]不用)
// char* codingSize;
// codingSize = (char*)malloc(sizeof(char) * n); // 分配求编码的工作空间
// codingSize[n-1] = '\0'; // 编码结束符
//
// for (nodeIndex = 1; nodeIndex <= n; nodeIndex++)
// { // 逐个字符求赫夫曼编码
// int pos;
// unsigned int c, f;
// pos = n - 1; // 编码结束位置
//
// for (c=nodeIndex, f=HT[nodeIndex].parent; f != 0; c=f, f = HT[f].parent)
// { // 从叶子到根逆向求编码
// if (HT[f].lchild == c)
// codingSize[--pos] = '0';
// else
// codingSize[--pos] = '1';
//
// HC[nodeIndex] = (char*)malloc((n - pos) * sizeof(char));
// // 为第i个字符编码分配空间
// strcpy(HC[nodeIndex], &codingSize[pos]); // 从codingSize复制编码串到HC
// }
// }
free(codingSize); // 释放工作区间
return;
}
// 求解赫夫曼编码
/************************************************************************/
void HuffmanTreeCoding(HuffmanTree &HT, HuffmanCode &HC, int* w, int n)
{ // w存放n个字符的权值(均>0), 构造赫夫曼树,求出n个字符的赫夫曼编码HC
if (n <= 1)
return;
int nNodes; // 总结点和
int nodeIndex; // 根结点序号
nNodes = 2 * n - 1;
HT = (HuffmanTree)malloc( sizeof(HTNode) * (nNodes+1) ); // 0号单元未用
HuffmanTree pTree;
pTree = HT+1;
for (nodeIndex=1; nodeIndex <= n; ++nodeIndex,++pTree, ++w)
{
pTree->weight = *w;
pTree->parent = 0;
pTree->lchild = 0;
pTree->rchild = 0;
}
for ( ; nodeIndex <= nNodes; ++nodeIndex, ++pTree)
(*pTree).parent = 0;
// 创建赫夫曼树
int minIndex1, minIndex2;
for (nodeIndex = n+1; nodeIndex <= nNodes; nodeIndex++) // 循环n-1次
{ // 在HT[1~nodeIndexs-1]中选择parent为0且weight最小的两个结点,其序号分别为minIndex1,minIndex2
Select(HT, nodeIndex-1, minIndex1, minIndex2);
HT[minIndex1].parent = HT[minIndex2].parent = nodeIndex;
HT[nodeIndex].lchild = minIndex1;
HT[nodeIndex].rchild = minIndex2;
HT[nodeIndex].weight = HT[minIndex1].weight + HT[minIndex2].weight;
}
HC = (HuffmanCode)malloc( (n+1)*sizeof(char*));
// 分配n个字符编码的头指针向量([0]不用)
char* codingSize;
codingSize = (char*)malloc(sizeof(char) * n); // 分配求编码的工作空间
unsigned int c, cdlen;
c = nNodes;
cdlen = 0;
for (int i=1; i <= nNodes; i++)
HT[i].weight = 0; // 遍历赫夫曼时用作结点标识
while (c)
{
if (HT[c].weight == 0)
{ // 向左
HT[c].weight = 1;
if (HT[c].lchild != 0)
{
c = HT[c].lchild;
codingSize[cdlen++] = '0';
}
else if (HT[c].rchild == 0)
{ // 登记叶子结点的字符编码
HC[c] = (char*)malloc((cdlen+1) * sizeof(char));
codingSize[cdlen] = '\0';
strcpy(HC[c], codingSize); // 复制编码(串)
}
}
else if (HT[c].weight == 1)
{ // 向右
HT[c].weight = 2;
if (HT[c].rchild != 0)
{
c = HT[c].rchild;
codingSize[cdlen++] = '1';
}
}
else
{ // HT[c].weight = 2, 退回
HT[c].weight = 0;
c = HT[c].parent;
--cdlen; // 退到父结点,编码长度减1
}
}
// // 从叶子到根逆向求每个字符的赫夫曼编码
// HC = (HuffmanCode)malloc( (n+1)*sizeof(char*));
//
// // 分配n个字符编码的头指针向量([0]不用)
// char* codingSize;
// codingSize = (char*)malloc(sizeof(char) * n); // 分配求编码的工作空间
// codingSize[n-1] = '\0'; // 编码结束符
//
// for (nodeIndex = 1; nodeIndex <= n; nodeIndex++)
// { // 逐个字符求赫夫曼编码
// int pos;
// unsigned int c, f;
// pos = n - 1; // 编码结束位置
//
// for (c=nodeIndex, f=HT[nodeIndex].parent; f != 0; c=f, f = HT[f].parent)
// { // 从叶子到根逆向求编码
// if (HT[f].lchild == c)
// codingSize[--pos] = '0';
// else
// codingSize[--pos] = '1';
//
// HC[nodeIndex] = (char*)malloc((n - pos) * sizeof(char));
// // 为第i个字符编码分配空间
// strcpy(HC[nodeIndex], &codingSize[pos]); // 从codingSize复制编码串到HC
// }
// }
free(codingSize); // 释放工作区间
return;
}
输出结果:
- 7.8 赫夫曼树应用解析(跟结点到叶子求每个字符的赫夫曼编码)
- 7.7 赫夫曼树应用解析(叶子到根逆向求每个字符的赫夫曼编码)
- 求根结点到每个叶子节点的逆序列【后序遍历非递归的应用】
- (HDU 2196) Computer <树型DP经典题目 & dfs> 求树上每个节点到最远的叶子结点的路径长度
- !求二叉树中从根结点到叶子结点的路径
- 求树的叶子结点的个数
- 求二叉树的叶子结点数
- 二叉树 (求叶子结点&深度)
- 二叉树(求深度、叶子结点)
- 求叶子结点个数
- 树-----求叶子结点数目,结点数目,树的高度
- HDU 2196 Computer(树形dp 求结点到叶子的最远距离)
- 数据结构--二叉树--输出树中从根到每个叶子节点的路径(树遍历算法的应用) .
- 打印从根结点到叶子结点的路径(递归)
- 打印二叉树根结点到所有叶子结点的路径
- 根结点到所有叶子结点的路径问题
- 二叉树的三种遍历的应用(表达式,求深度,叶子数,结点数,二叉树的建立,复制)
- 求森林叶子结点数
- 【Java教程】第二讲 Java语言基础知识
- 求最长的上升子序列
- LeetCode - Pow(x, n)
- UVA1366-----Martian Mining------DP
- android MotionEvent
- 7.8 赫夫曼树应用解析(跟结点到叶子求每个字符的赫夫曼编码)
- 《C语言深度剖析》学习笔记----C语言中的符号
- mysql解决中文乱码问题
- 计算角色和物体之间距离来触发动画【Unity3d】
- 对《RHCSA/RHCE Red Hat Linux认证学习指南(第6版):EX200 & EX300》的评价
- android frameworks
- 【JAVA教程】第三讲 Java语言中的面向对象特性
- 事件处理基础知识
- linux内核空间的内存映射