当前位置:   article > 正文

北邮数据结构:哈夫曼树_htree node

htree node

用类与对象C++编程

分为头文件Huffman.h

和主函数main.cpp两部分

(功能陆续添加)

类的声明:
 

  1. class Huffman
  2. {
  3. private:
  4. HNode*HTree;//哈夫曼树节点
  5. HCode*HCodeTable;//存储编码表
  6. int N;//叶子节点数量
  7. void code(int i, string newcode);//递归函数,对第i个节点编码
  8. public:
  9. Huffman() {
  10. HTree = new HNode; HCodeTable = new HCode; N = 0;
  11. };
  12. void CreateHTree(int a[], int n, char name[]);//构建哈夫曼树
  13. void CreateCodeTable();//创建编码表
  14. void Encode(string s, char *d);//编码
  15. void Decode(char *s, char *d);//解码
  16. ~Huffman();//析构函数
  17. void SelectMin(int &x, int &y, int a, int b);//辅助搜索最小值函数
  18. void Printeach(int retime);//打印每一个字母对应的编码
  19. };//类的定义

两种结点的定义:

树中结点和编码中的结点:

  1. struct HNode
  2. {
  3. int weight;//结点权值
  4. int parent;//双亲数组下标
  5. int LChild;//左孩子数组下标
  6. int RChild;//右孩子数组下标
  7. };//每个结点的结构体
  8. struct HCode
  9. {
  10. char data;//存储节点的内存
  11. string code;//存储结点对应的编码
  12. };//记录每个节点的编码

具体代码如下:

Huffman.h

  1. #include<iostream>
  2. #include<algorithm>
  3. using namespace std;
  4. #define manum 0x3f3f3f3f
  5. struct HNode
  6. {
  7. int weight;//结点权值
  8. int parent;//双亲数组下标
  9. int LChild;//左孩子数组下标
  10. int RChild;//右孩子数组下标
  11. };//每个结点的结构体
  12. struct HCode
  13. {
  14. char data;//存储节点的内存
  15. string code;//存储结点对应的编码
  16. };//记录每个节点的编码
  17. class Huffman
  18. {
  19. private:
  20. HNode*HTree;//哈夫曼树节点
  21. HCode*HCodeTable;//存储编码表
  22. int N;//叶子节点数量
  23. void code(int i, string newcode);//递归函数,对第i个节点编码
  24. public:
  25. Huffman() {
  26. HTree = new HNode; HCodeTable = new HCode; N = 0;
  27. };
  28. void CreateHTree(int a[], int n, char name[]);//构建哈夫曼树
  29. void CreateCodeTable();//创建编码表
  30. void Encode(string s, char *d,int &contro);//编码
  31. void Decode(char *s, char *d);//解码
  32. ~Huffman();//析构函数
  33. void SelectMin(int &x, int &y, int a, int b);//辅助搜索最小值函数
  34. void Printeach(int retime);//打印每一个字母对应的编码
  35. };//类的定义
  36. /****************************类的成员函数的实现*/
  37. //辅助函数,搜索数列中最小的两个结点值
  38. void Huffman::SelectMin(int &x, int &y, int a, int b)
  39. {
  40. //cout << a << " " << b << endl;
  41. //cout << HTree[b - 1].weight << endl;
  42. int m = manum, n = manum;//最小的两个数
  43. for (int i = a; i < b; i++)
  44. {
  45. if (HTree[i].weight < m)
  46. {
  47. m = HTree[i].weight;
  48. x = i;
  49. }
  50. }
  51. for (int i = a; i < b; i++)
  52. {
  53. if (HTree[i].weight < n&&i!=x)
  54. {
  55. n = HTree[i].weight;
  56. y = i;
  57. }
  58. }
  59. }
  60. //构造哈夫曼树
  61. //a[]存储每种字符的权值,n为字符的种类,name为各个字符的内容
  62. void Huffman::CreateHTree(int a[], int n, char name[])
  63. {
  64. N = n;
  65. HCodeTable = new HCode[N];
  66. HTree = new HNode[2 * N - 1];//2*n-1为总结点个数
  67. for (int i = 0; i < N; i++)
  68. {
  69. HTree[i].weight = a[i];
  70. HTree[i].LChild = HTree[i].RChild = HTree[i].parent = -1;
  71. HCodeTable[i].data = name[i];
  72. }
  73. int x, y;
  74. for (int i = n; i < 2 * N - 1; i++)//开始构建哈夫曼树
  75. {
  76. SelectMin(x, y, 0, i);//1~i中选出两个权值最小的结点
  77. //cout << "x=" << x <<" "<<HTree[x].weight<<endl;
  78. //cout << "y=" << y <<" "<<HTree[y].weight<<endl;
  79. HTree[x].parent = HTree[y].parent = i;
  80. HTree[i].weight = HTree[x].weight + HTree[y].weight;
  81. HTree[i].LChild = x;
  82. HTree[i].RChild = y;
  83. HTree[i].parent = -1;
  84. HTree[x].weight = HTree[y].weight = manum;
  85. }
  86. }
  87. //生成哈夫曼对应编码
  88. void Huffman::code(int i, string newcode)
  89. {
  90. if (HTree[i].LChild == -1)
  91. {
  92. HCodeTable[i].code = newcode;
  93. return;
  94. }
  95. code(HTree[i].LChild, newcode + '0');
  96. code(HTree[i].RChild, newcode + '1');
  97. }
  98. void Huffman::CreateCodeTable()//生成编码表
  99. {
  100. code(2 * N - 2, "");
  101. }
  102. //进行编码
  103. void Huffman::Encode(string s, char *d,int &contro)
  104. {
  105. contro = 0;
  106. int n2 = 0;//控制s的变量
  107. while (s[n2] != '\0')
  108. {
  109. for (int i = 0; i < N; i++)
  110. {
  111. if (HCodeTable[i].data == s[n2])
  112. {
  113. int k = 0;
  114. while (HCodeTable[i].code[k] != '\0')
  115. k++;//统计此字符对应编码的长度
  116. for (int j = 0; j < k; j++)
  117. {
  118. *d = HCodeTable[i].code[j];
  119. d++;
  120. contro++;
  121. }
  122. }
  123. }
  124. n2++;
  125. }
  126. }
  127. //进行解码
  128. void Huffman::Decode(char *s, char *d)
  129. {
  130. while (*s != '\0')
  131. {
  132. int parent = 2 * N - 2;//根结点在HTree的下标(有改动,原书中为2*n-2
  133. while (HTree[parent].LChild != -1)//如果叶子结点不是根结点
  134. {
  135. if (*s == '0')
  136. parent = HTree[parent].LChild;
  137. else
  138. parent = HTree[parent].RChild;
  139. s++;
  140. }
  141. *d = HCodeTable[parent].data;
  142. d++;
  143. }
  144. }
  145. //打印函数,打印每一个字符的编码
  146. void Huffman::Printeach(int retime)
  147. {
  148. cout << "每一个字符对应的编码如下:" << endl;
  149. for (int i = 0; i < retime; i++)
  150. {
  151. cout << "i=" << i << " " << HCodeTable[i].data << " " << HCodeTable[i].code << endl;
  152. }
  153. }
  154. //析构函数
  155. Huffman::~Huffman()
  156. {
  157. N = 0;
  158. HTree = NULL;
  159. HCodeTable = NULL;
  160. }
  161. //5.16更新,修改vs上出现字符错乱的bug

main.cpp

  1. #include<iostream>
  2. #include<cstring>
  3. #include<string>
  4. #include"Huffman.h"
  5. using namespace std;
  6. #define Size 100
  7. string str;
  8. char name[60];//字符类型(0-25为大写,30-55为小写,26为下划线)
  9. int Time[60];//字符的权值
  10. char name2[60];
  11. int Time2[60];
  12. int main()
  13. {
  14. cout << "请输入你想传递的字符串(空格用下划线代替),如想结束程序,请输入(END)" << endl;
  15. while (cin >> str)
  16. {
  17. if (str == "END")
  18. break;
  19. memset(Time, 0, sizeof(Time));
  20. memset(Time2, 0, sizeof(Time2));
  21. int len = str.size();
  22. if (len > Size)
  23. {
  24. cout << "数据量超过可处理范围" << endl;
  25. cout << "请输入你想传递的字符串(空格用下划线代替),如想结束程序,请输入(END)" << endl;
  26. continue;
  27. }
  28. for (int i = 0; i < len; i++)
  29. {
  30. if (str[i] == '_')
  31. {
  32. Time[26]++;
  33. name[26] = '_';
  34. }
  35. if (str[i] >= 'A'&&str[i] <= 'Z')
  36. {
  37. Time[str[i] - 'A']++;
  38. name[str[i] - 'A'] = str[i];
  39. }
  40. if (str[i] >= 'a'&&str[i] <= 'z')
  41. {
  42. Time[str[i] - 'a' + 30]++;
  43. name[str[i] - 'a' + 30] = str[i];
  44. }
  45. }//录入并处理字符串
  46. int retime = 0;//实际上出现的字符个数
  47. for (int i = 0; i < 60; i++)
  48. {
  49. if (Time[i] != 0)
  50. {
  51. name2[retime] = name[i];
  52. Time2[retime] = Time[i];
  53. retime++;
  54. }
  55. }
  56. //cout << "retime=" << retime << endl;
  57. name2[retime] = '\0';
  58. //精细化两个数组
  59. //运用类完成功能
  60. Huffman Huf;
  61. //cout << retime << endl;
  62. Huf.CreateHTree(Time2, retime, name2);
  63. Huf.CreateCodeTable(); //树和表的建立
  64. Huf.Printeach(retime);//打印每一个字符对应的哈夫曼编码
  65. char *ar = new char[Size];//编码后的字符串
  66. char *br = new char[Size];//解码后的字符串
  67. int contro=0;
  68. Huf.Encode(str, ar,contro);
  69. cout << "编码结果如下:" << endl;
  70. for (int i = 0; i < contro; i++)
  71. cout << *(ar + i);
  72. cout << endl;
  73. //cout << ar << endl;
  74. cout << "解码结果如下:" << endl;
  75. Huf.Decode(ar, br);
  76. for (int i = 0; i < len; i++)
  77. cout << *(br + i) ;
  78. cout << endl;
  79. cout << "定长编码需要的长度是:" << len*5 << ";" << "哈夫曼编码的长度是:" << contro << endl;
  80. cout << "原编码是新编码的" << len * 5 * 1.0 / contro <<"倍"<< endl;
  81. Huf.~Huffman();
  82. cout << endl;
  83. cout << "请输入你想传递的字符串(空格用下划线代替),如想结束程序,请输入(END)" << endl;
  84. }
  85. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/595994
推荐阅读
相关标签
  

闽ICP备14008679号