以下代码用C++实现了哈夫曼树的编码的过程,请解释每一步实现了什么操作,给出详细注释 class HuffmanNode { public: char symbol; unsigned long codeword, freq; unsigned int runLen, codewordLen; HuffmanNode* left, * right; HuffmanNode() { left = right = 0; } HuffmanNode(char s, unsigned long f, unsigned int r, HuffmanNode* lt = 0, HuffmanNode* rt = 0) { symbol = s; freq = f; runLen = r; left = lt; right = rt; } }; class ListNode { public: HuffmanNode* tree; ListNode* next, * prev; ListNode() { next = prev = 0; } ListNode(ListNode* p, ListNode* n) { prev = p; next = n; } }; void HuffmanCoding::encode(ifstream& fIn) { unsigned long packCnt = 0, hold, maxPack = bytes * bits, pack = 0; char ch, ch2; int bitsLeft, runLength; for (fIn.get(ch); !fIn.eof();) { for (runLength = 1, fIn.get(ch2); !fIn.eof() && ch2 == ch; runLength++) fIn.get(ch2); HuffmanNode* p = chars[(unsigned char)ch]; for (p = chars[(unsigned char)ch]; p != 0 && runLength != p->runLen; p = p->right); if (p == 0) cout<<("A promble in encode()"); if (p->codewordLen < maxPack - packCnt) { pack = (pack << p->codewordLen) | p->codeword; pack += p->codewordLen; } else { bitsLeft = maxPack - packCnt; pack <<= bitsLeft; if (bitsLeft != p->codewordLen) { hold = p->codeword; hold >>= p->codewordLen - bitsLeft; pack |= hold; } else pack |= hold; output(pack); if (bitsLeft != p->codewordLen) { pack = p->codeword; packCnt = maxPack - (p->codewordLen - bitsLeft); packCnt = p->codewordLen - bitsLeft; } else packCnt = 0; } ch = ch2; } if (packCnt != 0) { pack <<= maxPack - packCnt; output(pack); } }
时间: 2023-06-24 14:05:13 浏览: 83
这段代码实现了哈夫曼树的编码过程,包括读取文件中的字符并将其编码为哈夫曼编码,并将编码后的数据输出到另一个文件中。下面逐行解释每个部分的作用:
```c++
class HuffmanNode {
public:
char symbol; // 符号
unsigned long codeword, freq; // 编码和频率
unsigned int runLen, codewordLen; // 运行长度和编码长度
HuffmanNode *left, *right; // 左右子节点
HuffmanNode() {
left = right = 0;
}
HuffmanNode(char s, unsigned long f, unsigned int r, HuffmanNode *lt = 0, HuffmanNode *rt = 0) {
symbol = s;
freq = f;
runLen = r;
left = lt;
right = rt;
}
};
```
定义了一个哈夫曼树节点类,包含字符符号、编码、频率、运行长度、编码长度和左右子节点。有两个构造函数,一个是默认构造函数,将左右子节点初始化为 0,另一个是带参数的构造函数,用于创建节点。
```c++
class ListNode {
public:
HuffmanNode *tree;
ListNode *next, *prev;
ListNode() {
next = prev = 0;
}
ListNode(ListNode *p, ListNode *n) {
prev = p;
next = n;
}
};
```
定义了一个哈夫曼树节点列表类,包含一个哈夫曼树节点、前后指针,有两个构造函数,一个是默认构造函数,将前后指针初始化为 0,另一个是带参数的构造函数,用于创建节点列表。
```c++
void HuffmanCoding::encode(ifstream &fIn) {
unsigned long packCnt = 0, hold, maxPack = bytes * bits, pack = 0;
char ch, ch2;
int bitsLeft, runLength;
for (fIn.get(ch); !fIn.eof();) {
for (runLength = 1, fIn.get(ch2); !fIn.eof() && ch2 == ch; runLength++)
fIn.get(ch2);
HuffmanNode *p = chars[(unsigned char) ch];
for (p = chars[(unsigned char) ch]; p != 0 && runLength != p->runLen; p = p->right);
if (p == 0)
cout << ("A promble in encode()");
if (p->codewordLen < maxPack - packCnt) {
pack = (pack << p->codewordLen) | p->codeword;
pack += p->codewordLen;
} else {
bitsLeft = maxPack - packCnt;
pack <<= bitsLeft;
if (bitsLeft != p->codewordLen) {
hold = p->codeword;
hold >>= p->codewordLen - bitsLeft;
pack |= hold;
} else pack |= hold;
output(pack);
if (bitsLeft != p->codewordLen) {
pack = p->codeword;
packCnt = maxPack - (p->codewordLen - bitsLeft);
packCnt = p->codewordLen - bitsLeft;
} else packCnt = 0;
}
ch = ch2;
}
if (packCnt != 0) {
pack <<= maxPack - packCnt;
output(pack);
}
}
```
定义了一个哈夫曼编码函数 encode(),其中包含了对输入文件的读取过程、对字符进行编码的过程和对编码后的数据输出的过程。其中:
- packCnt 表示当前编码后数据的长度,hold 为一个临时变量,maxPack 为最大编码长度,pack 为编码后的数据;
- ch 和 ch2 为两个字符,用于从文件中读取字符;
- runLength 表示当前字符的运行长度;
- chars 为哈夫曼树节点数组,存储每个字符对应的哈夫曼树节点;
- p 为当前字符对应的哈夫曼树节点;
- 如果当前字符对应的哈夫曼编码长度小于剩余编码长度,则将当前字符的编码加入到 pack 中,并更新 packCnt 和 pack;
- 如果当前字符的编码长度大于剩余编码长度,则将 pack 向左移动剩余编码长度的位数,并将当前字符的编码加入到 pack 的右侧,然后将 pack 输出,并根据编码长度更新 pack 和 packCnt;
- 如果当前字符的编码长度等于剩余编码长度,则直接将当前字符的编码加入到 pack 的右侧,并将 pack 输出,然后将 packCnt 重置为 0;
- 最后,如果 packCnt 不为 0,则将 pack 左移 maxPack - packCnt 的位数,并将其输出。