数据结构实验(C++)
PS:仅数据结构实验记录
题目:根据哈夫曼(Huffman)编码的原理,编写一个程序,在用户输入节点权重的基础上建立它的哈夫曼编码。
#include<iostream>
using namespace std;
const int Max = 10;
struct ElemType
{
int weight; //记录权值,假定权值为整数
int parent, lchild, rchild; //游标
char hCode[Max]; //哈夫曼编码
//string Node;
};
//HuffmanTree类
class HuffmanTree
{
public:
HuffmanTree(int w[], int n); //有参构造函数
HuffmanTree(); //无参构造函数
void huffmanTreeCode( int n); //哈夫曼编码
void Print(); //输出路径
void PrintTreeCode(int n);
private:
ElemType* huffTree;
int num;
void Select(int n, int& i1, int& i2); //权值最小的根节点下标
};
//选取最小的两个权值下标
void HuffmanTree::Select(int n, int& i1, int& i2)
{
int i = 0, temp;
for (; i < n; i++) //寻找第一个没有双亲的节点,下标赋值给i1
if (huffTree[i].parent == -1) { i1 = i; break; }
for (i = i + 1; i < n; i++) //寻找第二个没有双亲的节点,下标赋值给i2
if (huffTree[i].parent == -1) { i2 = i; break; }
if (huffTree[i1].weight > huffTree[i2].weight)//比较i1和i2大小,小的下标赋给i1,大的i2
{
temp = i1; i1 = i2; i2 = temp;
}
for (i = i + 1; i < n; i++) // 遍历i后的权值,更新i1和i2
{
if (huffTree[i].parent == -1)
{
//权值小于i1,则i1赋值给i2、i赋值给i1
if (huffTree[i].weight < huffTree[i1].weight) {
i2 = i1; i1 = i;
}
else if (huffTree[i].weight < huffTree[i2].weight) //权值小于i2,i赋值给i2
{
i2 = i;
}
}
}
}
//有参构造函数
HuffmanTree::HuffmanTree(int w[], int n)
{
int i, k, i1, i2;
huffTree = new ElemType[2 * n - 1];
num = n;
for (i = 0; i < 2 * num - 1; i++) //初始化,所有结点均没有双亲和孩子
{
huffTree[i].parent = -1;
huffTree[i].lchild = huffTree[i].rchild = -1;
}
for (i = 0; i < num; i++) //存储叶子结点的权值
huffTree[i].weight = w[i];
for (k = num; k < 2 * num - 1; k++) //n-1次合并
{
Select(k, i1, i2); //权值最小的根结点下标为i1和i2
huffTree[k].weight = huffTree[i1].weight + huffTree[i2].weight;
huffTree[i1].parent = k; huffTree[i2].parent = k;
huffTree[k].lchild = i1; huffTree[k].rchild = i2;
}
}
//确定权值编码
void HuffmanTree::huffmanTreeCode(int n)
{
char hc[Max];
int hcLen;
int i, j, k, parent, p;
for (i = 0; i < n; i++)
{
hcLen = 0;
parent = huffTree[i].parent; //待编码字符的双亲结点下标
p = i;
while (parent != -1) //未到达根结点
{
if (huffTree[parent].lchild == p) //左孩子
hc[hcLen] = '0', hcLen++;
else if (huffTree[parent].rchild == p) //右孩子
hc[hcLen] = '1', hcLen++;
p = parent;
parent = huffTree[parent].parent; //继续向根结点查找
}
for (j = 0, k = hcLen - 1; j < hcLen; j++, k--) //将编码写入相应字符数组
huffTree[i].hCode[j] = hc[k];
huffTree[i].hCode[j] = '\0'; //字符串结束符
}
return;
}
//打印权值路径
void HuffmanTree::Print()
{
int i, k;
cout << "\n每个叶子到根结点的路径是:" << endl;
for (i = 0; i < num; i++)
{
cout << huffTree[i].weight;
k = huffTree[i].parent;
while (k != -1)
{
cout << "-->" << huffTree[k].weight;
k = huffTree[k].parent;
}
cout << endl;
}
cout << "\n";
}
//打印权值的哈夫曼编码
void HuffmanTree::PrintTreeCode(int n)
{
for (int i = 0; i < n; i++)
{
int j = 0;
cout << "权值为: " << huffTree[i].weight << "\t哈夫曼编码为: " << huffTree[i].hCode << endl;
}
}
//测试
int main()
{
cout << "请输入叶子节点的个数: ";
int n,j;
cin >> n;
int* w = new int[n];
for (int i = 0; i < n; i++)
{
cout << "请输入各叶子节点的权值大小(整数类型):";
cin >> j;
w[i] = j;
}
HuffmanTree T{ w, n };
T.huffmanTreeCode(n);
T.Print();
T.PrintTreeCode(n);
delete[]w;
return 0;
}
测试结果