头歌哈夫曼实验代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 rivejä
4.1 KiB

  1. // /Users/zhangzhiqi/Library/Mobile Documents/M6HJR9W95L~com~textasticapp~textastic/Documents/CLionProjects/TouGe-Huffman-Tree/SY1.cpp
  2. // Copyright (c) 2022.
  3. // @Time : 2022/4/30 16:27:25
  4. // @Author : 张稚琦
  5. // @Address: 湖北理工学院腾龙公寓 5620
  6. // @Email : zhang@zhang.mba / zhangzhiqi828@gmail.com / zhangzhiqi@lh83.onmicrosoft.com / 2272358828@qq.com
  7. // @File : SY1.cpp
  8. // @LastModified: 2022/4/30 下午4:25
  9. // @ProjectName : TouGe_Huffman_Tree
  10. # include <stdio.h>
  11. # include <iostream>
  12. # include <string.h>
  13. using namespace std;
  14. typedef struct //define structure HuffmanTree
  15. { int weight;
  16. int parent,lchild,rchild;
  17. }HTNode,*HuffmanTree;
  18. typedef char ** HuffmanCode;
  19. void Select(HuffmanTree HT,int end,int &s1,int &s2) ;//选出HT树到i为止,权值最小且parent为0的2个节点
  20. void HuffmanTreeing(HuffmanTree &HT,int *w,int n);//构建哈夫曼树函数
  21. void output(HuffmanTree HT,int m);//输出哈夫曼树
  22. int main()
  23. {
  24. HuffmanTree HT;
  25. HuffmanCode HC;
  26. int n,i;
  27. int *w;
  28. scanf("%d",&n);
  29. w=(int *)malloc(n*sizeof(int));
  30. for(i=0;i<n;i++)
  31. {
  32. scanf("%d",&w[i]);
  33. }
  34. HuffmanTreeing( HT , w ,n );
  35. cout<<"哈夫曼树:"<<endl;
  36. output(HT,2*n-1);
  37. return 0;
  38. }
  39. void Select(HuffmanTree HT,int end,int &s1,int &s2)
  40. { //选出HT树到i为止,权值最小且parent为0的2个节点
  41. //s1 is the least of HT[].weight
  42. //s2 is the second least of HT[].weight
  43. /********** Begin **********/
  44. int min1, min2;
  45. //遍历数组初始下标为 1
  46. int i = 1;
  47. //找到还没构建树的结点
  48. while(HT[i].parent != 0 && i <= end){
  49. i++;
  50. }
  51. min1 = HT[i].weight;
  52. s1 = i;
  53. i++;
  54. while(HT[i].parent != 0 && i <= end){
  55. i++;
  56. }
  57. //对找到的两个结点比较大小,min2为大的,min1为小的
  58. if(HT[i].weight < min1){
  59. min2 = min1;
  60. s2 = s1;
  61. min1 = HT[i].weight;
  62. s1 = i;
  63. }else{
  64. min2 = HT[i].weight;
  65. s2 = i;
  66. }
  67. //两个结点和后续的所有未构建成树的结点做比较
  68. for(int j=i+1; j <= end; j++)
  69. {
  70. //如果有父结点,直接跳过,进行下一个
  71. if(HT[j].parent != 0){
  72. continue;
  73. }
  74. //如果比最小的还小,将min2=min1,min1赋值新的结点的下标
  75. if(HT[j].weight < min1){
  76. min2 = min1;
  77. min1 = HT[j].weight;
  78. s2 = s1;
  79. s1 = j;
  80. }
  81. //如果介于两者之间,min2赋值为新的结点的位置下标
  82. else if(HT[j].weight >= min1 && HT[j].weight < min2){
  83. min2 = HT[j].weight;
  84. s2 = j;
  85. }
  86. }
  87. /********** End **********/
  88. }
  89. void HuffmanTreeing(HuffmanTree &HT,int *w,int n) //构建哈夫曼树函数
  90. { // w存放n个字符的权值(均>0),构造赫夫曼树HT
  91. /********** Begin **********/
  92. if(n<=1) return; // 如果只有一个编码就相当于0
  93. int m = 2*n-1; // 哈夫曼树总节点数,n就是叶子结点
  94. HT = (HuffmanTree) malloc((m+1) * sizeof(HTNode)); // 0号位置不用
  95. HuffmanTree p = HT;
  96. // 初始化哈夫曼树中的所有结点
  97. for(int i = 1; i <= n; i++)
  98. {
  99. (p+i)->weight = *(w+i-1);
  100. (p+i)->parent = 0;
  101. (p+i)->lchild = 0;
  102. (p+i)->rchild = 0;
  103. }
  104. //从树组的下标 n+1 开始初始化哈夫曼树中除叶子结点外的结点
  105. for(int i = n+1; i <= m; i++)
  106. {
  107. (p+i)->weight = 0;
  108. (p+i)->parent = 0;
  109. (p+i)->lchild = 0;
  110. (p+i)->rchild = 0;
  111. }
  112. //构建哈夫曼树
  113. for(int i = n+1; i <= m; i++)
  114. {
  115. int s1, s2;
  116. Select(HT, i-1, s1, s2);
  117. (HT)[s1].parent = (HT)[s2].parent = i;
  118. (HT)[i].lchild = s1;
  119. (HT)[i].rchild = s2;
  120. (HT)[i].weight = (HT)[s1].weight + (HT)[s2].weight;
  121. }
  122. /********** End **********/
  123. }
  124. void output(HuffmanTree HT,int m)
  125. { //输出哈夫曼树
  126. for(int i=1;i<=m;++i)
  127. {
  128. cout<<"HT["<<i<<"] ="<<HT[i].weight<<"\t"<<HT[i]. parent<<"\t";
  129. cout<<"\t" <<HT[i]. lchild <<"\t" <<HT[i]. rchild<<endl;
  130. }
  131. }