#include<iostream>
using namespace std;
#include<stdio.h>
#include <string.h>
#define MAX_CODE 10
class HNode{
public:
char c;//节点的字符
int weight;//节点的权重,即为出现的频率
int lchild;//节点的左孩子的编号
int rchild;//节点的右孩子的编号
char code[MAX_CODE];//节点得到的编码
HNode(){
weight = -1;
lchild = -1;
rchild = -1;
}
};
template <class Type>
void Swap(Type &a,Type &b){//交换a和b
Type temp = a;
a = b;
b = temp;
}
int Partition(HNode a[],int p,int r){
//将权重小于x的权重的点放在a[p]的左侧,
//权重大于x的权重的点放在a[p]的右侧
int i = p,j = r+1;
HNode x = a[p];
while (true){
while(a[++i].weight < x.weight && i < r);
while(a[--j].weight > x.weight);
if(i >= j)
break;
Swap(a[i],a[j]);
}
a[p] = a[j];
a[j] = x;
return j;
}
void QuickSort(HNode a[],int p,int r){//p为a数组的第一个,r为最后一个
if(p < r){
int q = Partition(a,p,r);//得到的q为基准元素最后在数组中的位置
QuickSort(a,p,q-1);//对左半段排序
QuickSort(a,q+1,r);//对右半段排序
}
}
void creatHuffmanTree(HNode a[],int num){
//创建哈夫曼树,如果有num个节点需要被编码,则共需要开辟2*num-1个空间
int left = 0;
int right = num;
for(int i = 0;i < num-1 && ((right+1) <= 2*num-1);i++){//需要循环num-1次确定num-1个度为2的节点,i < num-1
QuickSort(a,left,right-1);//right-1,因为如果有6个节点,QuickSort时的第三个参数是5
a[right].weight = a[left].weight + a[left+1].weight;
a[right].c = '#';//表示非叶子节点
a[right].lchild = left;
a[right].rchild = left+1;
left += 2;
right += 1;
}
}
void Encode(HNode a[],int index,int parent_index,char b = 'l'){
//节点数组a的最后一个元素的下标是2*num-1
if(parent_index == -1){
a[index].code[0] = '\0';
}
else
{
if(b == 'l')//左孩子
{
strcpy(a[index].code,a[parent_index].code);
strcat(a[index].code,"0");
}
if(b == 'r')//右孩子
{
strcpy(a[index].code,a[parent_index].code);
strcat(a[index].code,"1");
}
}
if(a[index].lchild != -1){
Encode(a,a[index].lchild,index,'l');
}
if(a[index].rchild != -1){
Encode(a,a[index].rchild,index,'r');
}
}
void main(){
int num;//节点数目
num = 5;
int numofspace = 9;//2*num-1
HNode a[9];
a[0].c = 'A';
a[0].weight = 9;
a[1].c = 'B';
a[1].weight = 48;
a[2].c = 'C';
a[2].weight = 32;
a[3].c = 'D';
a[3].weight = 12;
a[4].c = 'E';
a[4].weight = 24;
creatHuffmanTree(a,num);
Encode(a,2*num-2,-1);//注意,为什么是2*num-2?根节点本来就不需要管了
for(int i =0;i < 2*num-1;i++){//i < 2*num-1,为什么没有=?因为根节点本来就没有赋值
if(a[i].c != '#')
printf("%c:%s\n",a[i].c,a[i].code);
}
}
哈夫曼编码
最新推荐文章于 2022-10-07 15:11:55 发布