7-1 哈夫曼树哈夫曼编码
7-1 哈夫曼树哈夫曼编码
输入一组整型权值,构建哈夫曼树,实现哈夫曼编码,并输出带权路径长度。
输入格式:
第一行输入叶子结点个数,接着依次输入权值。
输出格式:
输出哈夫曼编码,输出带权路径长度。
输入样例:
在这里给出一组输入。例如:
8
5 29 7 8 14 23 3 11
输出样例:
在这里给出相应的输出。例如:
5编码为0001
29编码为10
7编码为1110
8编码为1111
14编码为110
23编码为01
3编码为0000
11编码为001
WPL:271
#include<iostream>
#include<string>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef struct{
int weight; //权重
int parent,lchild,rchild; //节点双亲,左右孩子
}HTNode,*HuffmanTree; //动态分配数组存哈夫曼树
int Select(HuffmanTree &HT, int n)
{
int p=0;
for(int i=1;i<=n;i++)
{
if(HT[i].parent==0 && (p==0||HT[i].weight < HT[p].weight))
{
p=i;
}
}
return p;
}
void CreateHuffmanTree(HuffmanTree &HT,int n)
{
if(n<=1) return;
int m = 2*n - 1;
HT = new HTNode[m+1];
for(int i = 1; i<=m ;i++) //初始化下标为0
{
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for(int i = 1; i <= n; i++)
{
cin>>HT[i].weight; //输入节点
}
for(int i=n+1; i <= m ;i++) //n-1次选择
{
//选择双亲为0,权值最小的节点,返回他们的序号s1,s2
int s1 = Select(HT, i-1);
HT[s1].parent = i; //删除s1,s2,双亲改为i
int s2 = Select(HT, i-1);
HT[s2].parent = i;
//s1,s2作为i的孩子
HT[i].lchild = s1;
HT[i].rchild = s2;
//i的权值等于孩子的权值之和
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
}
typedef char **HuffmanCode;
void CreateHuffmanCode( HuffmanTree HT,HuffmanCode &HC , int n)
{
HC = new char*[n+1]; //编码数组
char cd[n]; //临时编码数组
cd[n-1] = '\0'; //结束符
for(int i = 1; i<=n ;i++)
{
int start = n-1; //开始指向最后
int c = i;
int f = HT[i].parent; //f指向c的双亲
while( f!=0 )
{
--start; //回溯
if(HT[f].lchild == c)
cd[start] = '0';
else
cd[start] = '1';
//回溯
c = f;
f = HT[f].parent;
}
HC[i] = new char[n-start];
strcpy(HC[i] , &cd[start]);
}
//delete cd;
}
void show(HuffmanTree HT,HuffmanCode &HC , int n)
{
int wpl = 0;
for(int i=1;i<=n;i++)
{
string s = HC[i];
cout<<HT[i].weight<<"编码为"<<HC[i]<<endl;
wpl+=HT[i].weight*s.length();
}
cout<<"WPL:"<<wpl;
}
int main()
{
int n;
HuffmanTree HT = new HTNode;
cin>>n;
if(n==1||n==0)
{
cout<<"error";
return 0;
}
CreateHuffmanTree(HT,n);
HuffmanCode HC;
CreateHuffmanCode(HT ,HC,n );
show(HT ,HC,n);
return 0;
}