📄 huffman_base.cpp
字号:
#include "huffman_base.h"int huffman_base::get_code_len(int index){ check(); if (index < 0 || index >= (int)code_lens.size()) throw new huffman_exception("参数非法"); return code_lens[index];}vector<int> huffman_base::get_all_code_lens(void){ check(); return code_lens;}unsigned long huffman_base::get_code(int index){ check(); if (index < 0 || index >= (int)codes.size()) throw new huffman_exception("参数非法"); return codes[index];}vector<unsigned long> huffman_base::get_all_codes(void){ check(); return codes;}string huffman_base::get_code_str(int index){ check(); if (index < 0 || index >= (int)codes.size()) throw new huffman_exception("参数非法"); return long_to_string(codes[index], code_lens[index]);}vector<string> huffman_base::get_all_code_strs(void){ check(); vector<string> v; for(int i = 0; i < (int)codes.size(); i++) v.push_back(long_to_string(codes[i], code_lens[i])); return v;}int huffman_base::find(unsigned long code){ check(); for(int i = 0; i < (int)codes.size(); i++) if (codes[i] == code) return i; return -1;}int huffman_base::find(const string& code){ return find(string_to_long(code.c_str()));}inline void huffman_base::check(){ if (codes.size() <= 0) throw new huffman_exception("尚未调用过generate_codes()");}unsigned long huffman_base::string_to_long(const char* code){ unsigned long ret = 0; int len = (int)strlen(code); for(int i = len - 1; i >= 0; i--) if (code[i] == '1') ret |= (1ul << (len - i - 1)); return ret;}string huffman_base::long_to_string(unsigned long code, int code_len){ char* buf = new char[code_len + 1]; if (buf == NULL) throw new huffman_exception("no enough memory."); memset(buf, 0, code_len + 1); unsigned long bit = 1 << (code_len - 1); for(int i = 0; i < code_len; i++) { if (code & bit) buf[i] = '1'; else buf[i] = '0'; bit >>= 1; } string ret(buf); delete buf; return ret;}void huffman_base::generate_canonical_codes(){ if (code_lens.size() <= 0) throw new huffman_exception("生成Canonical Huffman编码前,应已知所有元素码长"); int max_code_len = 0; int min_code_len = 1000; const int tmp = sizeof(unsigned long) * 8 + 1; int len_count[tmp]; unsigned long min_code[tmp]; memset(len_count, 0, tmp * sizeof(int)); memset(min_code, 0, tmp * sizeof(unsigned long)); int num = (int)code_lens.size(); // 统计码长信息 for (int i = 0; i < num; i++) { int codelen = code_lens[i]; // huffman_base用unsigned long存储编码,因此 // 码长要限制在sizeof(unsigned long)*8以内 // 这里对超长的编码都简单忽略掉了 if ((unsigned long)codelen > sizeof(unsigned long)*8) continue; if (codelen > max_code_len) max_code_len = codelen; if (codelen < min_code_len) min_code_len = codelen; len_count[codelen]++; } // 计算特定码长的所有元素中最小的编码,这里使用的是 // Canonical Huffman编码规则,请参见相关文献 for (int i = max_code_len - 1; i >= 0; i--) min_code[i] = (min_code[i + 1] + len_count[i + 1]) >> 1; // 已知特定码长的所有元素中最小的编码,同样码长的元素, // 编码逐个加1就可以了 codes.clear(); for (int i = 0; i < num; i++) if (code_lens[i] > 0 && (unsigned long)code_lens[i] <= sizeof(unsigned long)*8) codes.push_back(min_code[code_lens[i]]++); else codes.push_back(0);}bool huffman_base::verify(){ check(); int max = 0; const int code_len_limit = 100; // 这里能检验的最大码长是100 int len_count[code_len_limit + 1]; memset(len_count, 0, sizeof(int)*(code_len_limit+1)); for(int i = 0; i < (int)code_lens.size(); i++) { if (code_lens[i] > code_len_limit) return true; // 如果有超长码,就不检验了 len_count[code_lens[i]]++; if (code_lens[i] > max) max = code_lens[i]; } // 从根开始,算每层分支结点数目,如果最后一层不为0,就表明Huffman树有错误 int nonleaf = 1; for(int i = 1; i <= max; i++) nonleaf = nonleaf * 2 - len_count[i]; return (nonleaf == 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -