图——哈夫曼编码

来源:互联网 发布:去哪里学淘宝运营 编辑:程序博客网 时间:2024/06/08 02:12

//// Created by getianao on 17-11-15.//#include <string>#include<iostream>#include <cstring>using namespace std;class codeInfo//字符原始数据{public:char value;int weight = 0;};class huffmanTreeNode//哈弗曼编码逻辑结构{public:int flag = 0;int weight;int parent, lChild, rChild;};class huffmanCode//哈弗曼编码{public:char value;char* code;int start;//记录编码开始位};//找出未连接节点的哈弗曼节点的最小值和次小值void select(huffmanTreeNode *ht, int index, int &s1, int &s2){s1 = 23767;s2 = 23767;int s1w = 23767;int s2w = 23767;for (int i = 1; i <= index; i++){if (ht[i].parent == 0){if (ht[i].weight<s1w){s2 = s1;s2w = s1w;s1w = ht[i].weight;s1 = i;}elseif (ht[i].weight<s2w){s2w = ht[i].weight;s2 = i;}}}}//生成哈弗曼编码void huffmanCoding(huffmanTreeNode *ht, huffmanCode *hc, codeInfo* w, int n){if (n <= 1)return;int m = 2 * n;//包括权值相加产生的结点for (int i = 1; i<m; i++)//将权值按顺序放进哈夫曼数组中,关系均初始化为0{if (i <= n){ht[i].weight = w[i].weight;}else{ht[i].weight = 0;}ht[i].parent = 0;ht[i].lChild = 0;ht[i].rChild = 0;}//建立哈夫曼树for (int i = n + 1; i<m; i++){int s1, s2;//权值中最小者和次小者的序号select(ht, i - 1, s1, s2);//在前i-1个权值中查找ht[s1].parent = i;ht[s2].parent = i;ht[i].lChild = s1;ht[i].rChild = s2;ht[i].weight = ht[s1].weight + ht[s2].weight;}/*//从下到上遍历建立哈夫曼编码for (int i = 1; i <= n; i++){hc[i].value = w[i].value;hc[i].code = new char[n];int start = n - 1;hc[i].code[n - 1] = '\0';//对于每一个元素查找他的哈夫曼编码;找他的双亲结点,如果他是双亲结点的左节点,当前位时0,否则是1for (int j = i, p = ht[i].parent; p != 0; j = p, p = ht[p].parent)//父节点存在,向上找{if (ht[p].lChild == j)hc[i].code[--start] = '0';elsehc[i].code[--start] = '1';}hc[i].start = start;}*///无栈非递归遍历哈弗曼树建立哈弗曼编码int cdlen = 0;char* cd = new char[n];int p = m - 1;//最后一个节点是哈弗曼节点的根节点while (p){if (ht[p].flag == 0)//向左遍历{ht[p].flag = 1;if (ht[p].lChild != 0)//左孩子存在{p = ht[p].lChild;cd[cdlen++] = '0';}else if (ht[p].rChild == 0)//左右孩子皆不存在{hc[p].value = w[p].value;hc[p].code = new char[n];cd[cdlen] = '\0';for (int i = 0; i <= cdlen; i++){hc[p].code[i] = cd[i];}}}else if (ht[p].flag == 1)//向右遍历{ht[p].flag = 2;if (ht[p].rChild != 0){p = ht[p].rChild;cd[cdlen++] = '1';}}else{ht[p].flag = 0;p = ht[p].parent;cdlen--;}}}void outputHuffmanCode(huffmanCode *hc, int n){for (int i = 1; i <= n; i++){cout << "字符:" << hc[i].value << "对应编码:";cout << hc[i].code;// int j = hc[i].start;// for (; j < n - 1; j++)// {//     cout << hc[i].code[j];// }cout << endl;}}codeInfo*  input(int n)//手动输入字符频率{codeInfo* w = new codeInfo[n + 1];for (int i = 1; i <= n; i++){cout << "请输入字符:";cin >> w[i].value;cout << "请输入权重:";cin >> w[i].weight;}return w;}codeInfo*  stringScanInput(string str, int &n)//输入字符串自动统计字符频率  //理论上支持标准ASCII码及扩展ASCII码范围的字符{codeInfo* w = new codeInfo[256];n = 0;char* buffer = new char[str.size() + 1];strcpy_s(buffer, str.size() + 1, str.c_str());codeInfo* m = new codeInfo[256];for (int i = 0; i<str.size(); i++){m[(int)buffer[i]].value = buffer[i];m[(int)buffer[i]].weight++;}for (int i = 0; i<256; i++){if (m[i].weight){n++;w[n].value = m[i].value;w[n].weight = m[i].weight;}}return w;}//解哈夫曼码返回元素序号void deHuffmanCode(huffmanTreeNode *ht, huffmanCode *hc, const char *code, int n){int p = 2 * n - 1;int i = 0;while (code[i] != '\0'){if (code[i] == '0')p = ht[p].lChild;elsep = ht[p].rChild;if (ht[p].lChild == 0 && ht[p].rChild == 0){cout << hc[p].value;i++;p = 2 * n - 1;continue;}i++;}}int main(){int n;codeInfo* w = NULL;huffmanTreeNode *ht;huffmanCode *hc;string str, huffmanCodeString;int index;cout << "请输入输入方式(1/2):" << endl;cout << "1.手动输入字符频率" << endl;cout << "2.输入字符串自动统计字符频率" << endl;cin >> index;cout << "*************************" << endl;switch (index){case 1:cout << "请输入字符个数";cin >> n;w = input(n);cout << "请输入原始字符串:";cin >> str;break;case 2:cout << "请输入原始字符串:";cin >> str;w = stringScanInput(str, n);//同时返回n:字符种类数量break;}ht = new huffmanTreeNode[2 * n];hc = new huffmanCode[n + 1];huffmanCoding(ht, hc, w, n);outputHuffmanCode(hc, n);//打印哈弗曼编码对应关系char* buffer = new char[str.size() + 1];strcpy_s(buffer, str.size() + 1, str.c_str());cout << "编码后";for (int i = 0; i <= str.size(); i++){for (int j = 0; j <= n; j++){if (hc[j].value == buffer[i]){cout << hc[j].code;break;}}}cout << endl;cout << "请输入待解码赫夫曼编码字符串:" << endl;cin >> huffmanCodeString;deHuffmanCode(ht, hc, huffmanCodeString.c_str(), n);cout << endl;return 0;}




原创粉丝点击