哈夫曼算法
哈夫曼算法的一般步骤如下:
1.初始化:由给定的 个权值构造
n
n
n棵只有一个根节点的二叉树,得到一个二叉树集合
F
F
F 。
2.选取与合并:从二叉树集合
F
F
F中选取根节点权值 最小的两棵 二叉树分别作为左右子树构造一棵新的二叉树,这棵新二叉树的根节点的权值为其左、右子树根结点的权值和。
3.删除与加入:从
F
F
F中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到
F
F
F中。
4.重复 2、3 步,当集合中只剩下一棵二叉树时,这棵二叉树就是霍夫曼树。
代码
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#define N 1000
using namespace std;
typedef struct HNode{
int weight;
HNode *lchild,*rchild;
} *Htree;
Htree createHuffmanTree(int arr[],int n){
//构建哈夫曼树
Htree forest[N];
Htree root=NULL;
for(int i=0;i<n;i++){
Htree temp;
temp=(Htree)malloc(sizeof(HNode));
temp->weight=arr[i];
temp->lchild=temp->rchild=NULL;
forest[i]=temp;
}
for(int i=0;i<n-1;i++){ //n个节点合并成一颗树需要进行n-1次合并操作
int Min=-1,Minsub;//Min为最小树根的下标,Minsub为次小树根的下标
for(int j=0;j<n;j++){
if(Min==-1&&forest[j]!=NULL){
Min=j;
continue;
}
if(forest[j]!=NULL){
Minsub=j;
break;
}
}
for(int j=Minsub;j<n;j++){
if(forest[j]!=NULL){
if(forest[j]->weight<forest[Min]->weight){
Minsub=Min;
Min=j;
}
else if(forest[j]->weight<forest[Minsub]->weight)
Minsub=j;
}
}
printf("%d %d\n",forest[Min]->weight,forest[Minsub]->weight);
root=(Htree)malloc(sizeof(HNode));
root->weight=forest[Min]->weight+forest[Minsub]->weight; // 根节点的权值为两个叶子节点之和
root->lchild=forest[Min];
root->rchild=forest[Minsub];
forest[Min]=root;//指向新树的指针赋给Min的位置
forest[Minsub]=NULL;//将Minsub位置赋为空
}
//printf("%d\n",root->weight);
return root;
}
int getWPL(Htree root,int len){
//对于已建好的哈夫曼树,求其WPL
if(root==NULL)
return 0;
if(root->lchild==NULL&&root->rchild==NULL){
return (root->weight)*len;
}
int left,right;
left=getWPL(root->lchild,len+1);
right=getWPL(root->rchild,len+1);
return left+right;
}
int getWPL(int arr[], int n) {
// 对于未建好的哈夫曼树,直接求其WPL
//树的WPL==所有非叶子结点之和
priority_queue<int, vector<int>, greater<int>> huffman; //小根堆
for (int i = 0; i < n; i++) huffman.push(arr[i]);
int res = 0;
for (int i = 0; i < n - 1; i++) {
int x = huffman.top();
huffman.pop();
int y = huffman.top();
huffman.pop();
int temp = x + y;
res += temp;
printf("%d\n",res);
huffman.push(temp);
}
return res;
}
void huffmanCoding(Htree root,int len,char *cod){
if(root!=NULL){
if(root->lchild==NULL&&root->rchild==NULL){
printf("权值为%d的结点的哈夫曼编码为:\n",root->weight);
cod[len]='\0';
printf("%s",cod);
printf("\n");
}
else{
cod[len]='0';
huffmanCoding(root->lchild,len+1,cod);
cod[len]='1';
huffmanCoding(root->rchild,len+1,cod);
}
}
}
void Preorder(Htree tree){
if(tree==NULL)
return ;
printf("%d ",tree->weight);
Preorder(tree->lchild);
Preorder(tree->rchild);
}
int main()
{
int arr[6]={3,1,5,6,2,8};
char s[100];
Htree HuffmanTree=createHuffmanTree(arr,6);
Preorder(HuffmanTree);
printf("\n");
printf("WPL:%d\n",getWPL(HuffmanTree,0));
huffmanCoding(HuffmanTree,0,s);
//printf("WPL2:%d\n",getWPL(arr,6));
return 0;
}