#include<bits/stdc++.h>
using namespace std;
typedef char* HuffmanCode;
const int MAXN = 110;
typedef struct {
int parent, lchild, rchild;
int weight;
} HuffmanNode, * HuffmanTree;
void selectMin(HuffmanTree HT, int n, int& s1, int& s2) {
int min = INT_MAX;
for (int i = 1; i <= n; ++i) {
if (HT[i].parent == 0 && min > HT[i].weight) {
min = HT[i].weight;
s1 = i;
}
}
min = INT_MAX;
for (int i = 1; i <= n; ++i) {
if (HT[i].parent == 0 && min > HT[i].weight && i != s1) {
min = HT[i].weight;
s2 = i;
}
}
if (s1 > s2) {
swap(s1, s2);
}
}
//无栈非递归遍历哈夫曼树,求哈夫曼编码
void HuffmanCoding(HuffmanTree& HT, HuffmanCode*& HC, int w[], int n) {
if (n <= 1) return;
int m = 2 * n - 1; //m是因为需要(n - 1)次合并,所以总共要有(n + n - 1)个数据要存储
//分配n个字符编码的头指针向量[0]不用
HT = new HuffmanNode[m + 1];
// 初始权值存储
for (int i = 1; i <= n; ++i) {
HT[i].weight = w[i];
HT[i].parent = HT[i].lchild = HT[i].rchild = 0;
}
// 要存储的合并后权值的初始化
for (int i = n + 1; i <= m; ++i) {
HT[i].parent = HT[i].lchild = HT[i].rchild = 0;
}
//构建哈夫曼树
for (int i = n + 1; i <= m; ++i) {
int s1, s2;
selectMin(HT, i - 1, s1, s2);
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[s1].parent = HT[s2].parent = i;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
//分配n个字符编码的头指针向量([0]不用)
HC = new HuffmanCode[n + 1];
char* cd = new char[n];
int c = m;
int cdlen = 0;
cd[n - 1] = '\0';
for (int i = 1; i <= m; ++i) {
HT[i].weight = 0;//遍历哈夫曼树作结点状态标志
}
// 贪心算法,0表示结点左孩子右孩子都没访问,1表示结点左孩子访问了,右孩子还没访问,2表示左右孩子都访问了。
while (c) {
if (HT[c].weight == 0) {//向左
HT[c].weight = 1;
if (HT[c].lchild != 0) {
c = HT[c].lchild;
cd[cdlen++] = '0';
}
else if (HT[c].rchild == 0) {//登记叶子结点的编码
HC[c] = new char[cdlen + 1];
cd[cdlen] = '\0';
strcpy(HC[c], cd);//复制编码(串)
}
}
else if (HT[c].weight == 1) { //向右
HT[c].weight = 2;
if (HT[c].rchild != 0) {
c = HT[c].rchild;
cd[cdlen++] = '1';
}
}
else {//HT[c].weight == 2, 退回
c = HT[c].parent;
--cdlen;//退回父结点,编码长度减一
}
}
delete[]cd;
}
int main() {
HuffmanTree HT;
HuffmanCode* HC;
int n;
int data[MAXN];
while (scanf("%d", &n) != EOF) {
for (int i = 1; i <= n; ++i) {
scanf("%d", &data[i]);
}
HuffmanCoding(HT, HC, data, n);
for (int i = 1; i <= n; ++i) {
printf("%s\n", HC[i]);
}
delete(HC);
delete(HT);
}
return 0;
}
问题 H : 算法6 - 12:自底向下的赫夫曼编码
最新推荐文章于 2025-05-28 22:18:33 发布