/*
哈夫曼树
结果带权路径长度(WPL)最小
(1) 以权值分别为W1,W2...Wn的n各结点,构成n棵二叉树T1,T2,...Tn并组成森林F={T1,T2,...Tn},其中每棵二叉树 Ti仅有一个权值为 Wi的根结点;
(2) 在F中选取两棵根结点权值最小的树作为左右子树构造一棵新二叉树,并且置新二叉树根结点权值为左右子树上根结点的权值之和(根结点的权值=左右孩子权值之和,叶结点的权值= Wi)
(3) 从F中删除这两棵二叉树,同时将新二叉树加入到F中;
(4) 重复(2)、(3)直到F中只含一棵二叉树为止,这棵二叉树就是Huffman树。
*/
#include <iostream>
#include<iomanip>
using namespace std;
#define NODE_NUM 16 //叶子结点个数
#define MAXVAL 32767
//哈夫曼树的存储表示
typedef struct
{
int weight; // 权值
int parent, lchild,rchild; // 双亲及左右孩子的下标
}HuffmanTree;
typedef struct { //哈夫曼编码结构体
int bit[8]; //存放当前结点的哈夫曼编码
int start; //bit[start]-bit[8]存放哈夫曼编码
}HCodeType;
HuffmanTree HuffNode[NODE_NUM]; //定义全局变量数组HuffNode存放哈夫曼树
HCodeType HuffCode[8]; //定义全局变量数组HuffCode存放哈夫曼编码
int n;//叶子个数
//构建哈弗曼树
void CreateHuffmanTree()
{
int min1, min2;//两个最小权值
int p1, p2;//两个最小权值结点的数组下标
cout << "输入叶子结点个数" << endl;
cin >> n;
if (2*n>NODE_NUM)
{
cout << "原本预设的叶子结点个数宏不够大";
}
for (int i = 0; i < 2 * n-1; i++) //HuffNode 初始化
{
HuffNode[i].weight = 0;
HuffNode[i].parent = 0;
HuffNode[i].lchild = 0;
HuffNode[i].rchild = 0;
}
cout << "输入带权结点" << endl;
for (int i=0;i<n;i++)
{
cin >> HuffNode[i].weight;
}
for (int i=n;i<2*n-1;i++)
{
min1 = min2 = MAXVAL;
p1 = p2 = 0;
for (int j=0;j<i;j++)
{
if (HuffNode[j].parent==0)
{
if (HuffNode[j].weight<min1)
{
min2 = min1;
min1 = HuffNode[j].weight;
p2 = p1;
p1 = j;
}
else if (HuffNode[j].weight<min2)
{
min2 = HuffNode[j].weight;
p2 = j;
}
}
}
HuffNode[p1].parent = HuffNode[p2].parent = i+1;
HuffNode[i].lchild = p1+1;
HuffNode[i].rchild = p2+1;
HuffNode[i].weight = HuffNode[p1].weight + HuffNode[p2].weight;
}
}
//输出哈夫曼树
void PrintHuffTree()
{
int i;
cout << endl;
cout << "哈夫曼树各项数据如下表所示:" << endl;
cout << "结点i weight parent lchid rchild" << endl;
for (i = 0; i < 2 * n - 1; i++)
cout << i + 1 << setw(8) << HuffNode[i].weight << setw(8) << HuffNode[i].parent << setw(8) << HuffNode[i].lchild << setw(8) << HuffNode[i].rchild <<endl;
/*printf("%d\t%d\t%d\t%d\t%d\n", i+1, HuffNode[i].weight, HuffNode[i].parent,
HuffNode[i].lchild, HuffNode[i].rchild);*/
cout << endl;
}
//构造哈夫曼编码
void CreateHuffCode()
{
HCodeType cd;
int c, p;
for (int i = 0; i <n; i++)
{
cd.start = n;
c = i+1;
p = HuffNode[i].parent;
while (p)
{
cd.start--;
if (HuffNode[p-1].lchild == c)
cd.bit[cd.start] = 0;
else
cd.bit[cd.start] = 1;
c = p;
p = HuffNode[p-1].parent;
}
for (int j = cd.start; j < n; j++)
HuffCode[i].bit[j] = cd.bit[j];
HuffCode[i].start = cd.start;
}
}
//输出每个叶子结点的哈夫曼编码
void PrintHuffcode(void) {
int i, j;
cout << "每个叶子结点的哈夫曼编码为:" << endl;
for (i = 0; i <n; i++)
{
for (j = HuffCode[i].start; j < n; j++)
cout << HuffCode[i].bit[j];
cout << endl;
}
}
int main()
{
CreateHuffmanTree();
PrintHuffTree();
CreateHuffCode();
PrintHuffcode();
return 0;
}
哈夫曼树以及哈夫曼编码|数据结构
最新推荐文章于 2022-12-09 19:08:58 发布