1 #include <iostream> 2 using std::cout; 3 using std::cin; 4 using std::endl; 5 6 #include <iomanip> 7 using std::setw; 8 9 // ------------赫夫曼树和赫夫曼编码的存储表示------------- 10 typedef struct 11 { 12 unsigned int weight; 13 unsigned int parent, lchild, rchild; 14 } HTNode, * HuffmanTree; // 动态分配数组存储赫夫曼树 15 typedef char * HuffmanCodeLine; 16 typedef char * * HuffmanCode; // 动态分配数组存储赫夫曼编码表 17 typedef struct{ 18 unsigned int weight; 19 int index; 20 }Non_parent; //存储没有父节点的HuffmanTree的权重和序号 21 22 void Select(HuffmanTree &HT, int count, int &min1, int &min2); 23 24 void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int * w, int n) 25 { 26 // w存放n个字符的权值(均>0), 构造赫夫曼树HT, 27 // 并求出n个字符的赫夫曼编码HC. 28 if (n <= 1) 29 { 30 return; 31 } 32 int m = 2*n-1; // n个叶子结点的赫夫曼树共有2*n-1个结点. 33 HT = new HTNode[m+1]; // 0号单元未用. 34 int i; // 循环变量 35 HTNode * p; 36 for (p=HT+1, i=1; i<=n; ++i, ++p, ++w) // 0号单元未用. 37 { 38 (*p).weight = *w; 39 (*p).parent = 0; 40 (*p).lchild = 0; 41 (*p).rchild = 0; 42 } 43 for (; i<=m; ++i, ++p) 44 { 45 (*p).weight = 0; 46 (*p).parent = 0; 47 (*p).lchild = 0; 48 (*p).rchild = 0; 49 } 50 int s1, s2; 51 for (i=n+1; i<=m; ++i) 52 { 53 // 建赫夫曼树: 54 // 在HT[1...i-1]选择parent为0且weight最小的两个结点, 55 // 其序号分别为s1和s2. 56 Select(HT, i-1, s1, s2); 57 HT[s1].parent = i; 58 HT[s2].parent = i; 59 HT[i].lchild = s1; 60 HT[i].rchild = s2; 61 HT[i].weight = HT[s1].weight + HT[s2].weight; 62 } 63 #if 1 64 // ---------从叶子到根逆向求每个字符的赫夫曼编码--------- 65 HC = new char*[n+1]; // 分配n个字符编码的头指针向量 66 // 也是0号单元未用!!! 67 char * cd = new char[n]; // 分配求编码的工作空间 68 cd[n-1] = '\0'; // 编码结束码 69 int start; 70 for (i=1; i<=n; ++i) 71 { 72 start = n-1; // 编码结束符位置 73 int l; 74 unsigned int f; 75 for (l=i, f=HT[i].parent; f!=0; l=f, f=HT[f].parent) 76 { 77 if (HT[f].lchild == l) 78 { 79 cd[--start] = '0'; 80 } 81 else 82 { 83 cd[--start] = '1'; 84 } 85 } 86 HC[i] = new char[n - start]; 87 strcpy(HC[i], &cd[start]); 88 } 89 delete [] cd; // 释放工作空间 90 #else 91 // ---------无栈非递归遍历赫夫曼树, 求赫夫曼编码--------- 92 // ... 93 #endif 94 }131 void Select(HuffmanTree &HT, int count, int &min1, int &min2){ 132 int j=0; 133 int j_index=0; 134 Non_parent* n_parent=nullptr; 135 n_parent=new Non_parent[count]; 136 for(int i=1;i<=count;i++){ 137 if(HT[i].parent==0){ 138 n_parent[j].weight=HT[i].weight; 139 n_parent[j].index=i; 140 j++; 141 } 142 } 143 int jMax=j; 144 unsigned int temp=n_parent[0].weight; 145 min1=n_parent[0].index; 146 for(j=1;j<jMax;j++){ //找出权重最小的节点 147 if(n_parent[j].weight<temp){ 148 temp=n_parent[j].weight; 149 min1=n_parent[j].index; 150 j_index=j; 151 } 152 } 153 for(int i=j_index;i<jMax-1;i++){ //去掉权重最小的节点 154 n_parent[i]=n_parent[i+1]; 155 } 156 temp=n_parent[0].weight; 157 min2=n_parent[0].index; 158 for(j=1;j<jMax-1;j++){ //找出权重第二小的节点 159 if(n_parent[j].weight<temp){ 160 temp=n_parent[j].weight; 161 min2=n_parent[j].index; 162 } 163 } 164 delete[] n_parent; 165 n_parent=nullptr; 166 167 168 } 169 170 171 172 173 174 175 176 177 178 179 int main() 180 { 181 int i = 0; 182 int cntLeaf = 0; 183 int cntNode = 0; 184 185 cout << "请输入叶子个数(正整数): "; 186 cin >> cntLeaf; 187 while (cntLeaf <= 0) 188 { 189 cout << "叶子个数不能为0, 请重新输入: "; 190 cin >> cntLeaf; 191 } 192 193 cntNode = cntLeaf*2-1; 194 char * pLetter = new char[cntLeaf]; 195 int * pWeight = new int[cntLeaf]; 196 for (i=0; i<cntLeaf; ++i) 197 { 198 cout << "请分别输入叶子结点的字符值和权值: "; 199 cin >> pLetter[i] >> pWeight[i]; 200 } 201 202 HuffmanTree HT = NULL; 203 HuffmanCode HC = NULL; 204 HuffmanCoding(HT, HC, pWeight, cntLeaf); 205 206 cout << "Huffman树结构如下:\n"; 207 cout << setw(7) << "No." 208 << setw(6+1) << "weight" 209 << setw(6+1) << "parent" 210 << setw(6+1) << "lchild" 211 << setw(6+1) << "rchild" 212 << '\n'; 213 for (i=0; i<cntNode; ++i) 214 { 215 cout << setw(6+1) << i+1 216 << setw(6+1) << HT[i+1].weight 217 << setw(6+1) << HT[i+1].parent 218 << setw(6+1) << HT[i+1].lchild 219 << setw(6+1) << HT[i+1].rchild 220 << '\n'; 221 } 222 223 cout << "\n各叶子结点的Huffman编码如下:\n"; 224 for (i=0; i<cntLeaf; ++i) 225 { 226 cout << pLetter[i] << ' ' << HC[i+1] << '\n'; 227 } 228 229 for(int i=1;i<cntLeaf+1;i++){ 230 delete[] HC[i]; 231 HC[i]==nullptr; 232 } 233 234 delete[] HT; 235 HT=nullptr; 236 delete[] HC; 237 HC=nullptr; 238 delete[] pLetter; 239 pLetter=nullptr; 240 delete[] pWeight; 241 pWeight=nullptr; 242 243 return 0; 244 } 245