1.哈夫曼编码的结点类:
struct HuffmanNode {
int weight; // 权重,出现的次数或者频率
char ch; // 存储符号
string code; // 存储该符号对应的编码
int leftChild, rightChild, parent; // 左、右孩子,父结点
};
2.思路:
(1)统计输入的字符串中不同字符的出现的次数,作为权值,然后存到哈夫曼编码数组中:
// 2.统计输入的字符串的各个字符出现的个数
memset(arr, 0, sizeof(arr)); // 清零
for(i = 0; i < len; i++) // 统计次数
arr[str[i]]++; // str[i] -> 转成对应的ASCII码,如'0'->48
leafSize = 0; // 出现不同字符的个数
for(i = 0; i < 256; i++) {
if(arr[i] != 0) { // 有出现的字符
// cout << "字符:" << (char)i << "次数为:" << arr[i] << endl;
HuffmanTree[leafSize].ch = (char)i; // 将数字转成对应的字符
HuffmanTree[leafSize].weight = arr[i]; // 权重
leafSize++;
}
}
(2)然后,根据Huffman树的原理:权值越大的离根越近,权值越小的离根越远,建立Huffman树;
// 3.选取两个较小值合并
int first, second; // 两个较小的结点
for(i = leafSize; i < (2*leafSize-1); i++) { // 做leafSize-1趟
getMin(first, second, i); // 选取两个较小的元素
Merge(first,second,i); // 合并
}
(3)编码:接着,从叶子结点出发,如果该结点为父结点的左孩子,则在编码追加“0”;
如果为其右孩子,则编码追加“1”,
注意:上面得到的编码要倒过来存放。因为字符对应的编码是从根到叶子结点所得到的编码ÿ