**哈夫曼树:**给定一组具有确定权值的叶子结点,带权路径长度最小的二叉树。
哈夫曼树(n个结点构造哈夫曼树,总共需要2n-1大小的数组存储)
huffTree数组[权值weight、双亲parent、左孩子lchild、右孩子rchild]
1.数组HuffNode初始化,所有元素结点的双亲、左右孩子都置为-1;
2.数组HuffNode的前n个元素的权值置给定值w[n];
3.进行n-1次合并.在二叉树集合中选取两个权值最小的根结点,其下标分别为x1,x2; 将二叉树x1,x2合并为一棵新的二叉树k
(1)赋新权;
(2)x1、x2的双亲结点为k;
(3)更新该结点的左孩子为x1,右孩子为x2;
(4)将i1和i2删去;
*键盘输入n,定义动态数组的方法:int a=new int[n]
代码如下:
#include<iostream>
#include <string.h>
using namespace std;
#define MAXVALUE 2147483647 //最大权值
/*哈夫曼树的数据结构*/
typedef struct{
int weight; //权值
int parent; //父节点下标
int lchild; //左孩子节点的下标
int rchild; //右孩子节点的下标
} HTNodeType;
//函数声明
void HuffmanTree(HTNodeType HuffNode[],int n); //1 创建哈夫曼树
void HuffmanCode(HTNodeType HuffNode[],char *huffCode[], int n); //2 求哈夫曼编码
int main(){
int n;//结点个数
cout<<"输入结点个数:";
cin>>n;
HTNodeType *HuffNode=new HTNodeType[2*n-1];//哈夫曼树结点数组
int *weight=new int[n];//权值数组
char **huffCode=new char*[n];//指针数组,指向n个哈夫曼编码字符串
HuffmanTree(HuffNode,n);
HuffmanCode(HuffNode,huffCode,n);
cout<<"哈夫曼编码:"<<endl;
for(int i=0;i<=n;i++){
cout<<huffCode[i]<<endl;
}
return 0;
}
//创建哈夫曼树
void HuffmanTree(HTNodeType HuffNode[],int n)
{
int i = 0, j = 0;
for (i = 0; i < 2 * n - 1; i++){//初始化所有结点的项目为-1
HuffNode[i].weight = 0;
HuffNode[i].parent = -1;
HuffNode[i].lchild = -1;
HuffNode[i].rchild = -1;
}
cout<<"输入"<<n<<"个权值:";
for(i=0;i<n;i++){//输入权值
cin>>HuffNode[i].weight;
}
for (i = 0; i < n - 1; i++){ //找到parent为-1的最小和次小的结点
int m1 = MAXVALUE, m2 = MAXVALUE, x1 = -1, x2 = -1;
for (j = 0; j < n + i; j++){
if (HuffNode[j].weight < m1 && HuffNode[j].parent == -1){
m2 = m1;
x2 = x1;
m1 = HuffNode[j].weight;
x1 = j;
}
else if (HuffNode[j].weight < m2 && HuffNode[j].parent == -1){
m2 = HuffNode[j].weight;
x2 = j;
}
}
//选中x1,x2合并,更新结点
HuffNode[n + i].weight = m1 + m2;//新的结点权值为x1和x2的权值之和
HuffNode[x1].parent = n + i;//x1的双亲结点为新结点
HuffNode[x2].parent = n + i;//x2的双亲结点为新结点
HuffNode[n + i].lchild = x1;//左孩子为x1
HuffNode[n + i].rchild = x2;//右孩子为x1
}
}
//从叶子到根逆向求每个字符的哈夫曼编码
void HuffmanCode(HTNodeType HuffNode[], char *huffCode[],int n)
{
char *temp=new char[n];//定义工作空间,存储临时产生的编码串
temp[n-1] ='\0';
int start,pos;
for (int i = 0; i < n; i++){//遍历哈夫曼树数组,生成哈夫曼编码
start=n-1;
pos=i;//pos记录正在处理的当前位置,也就是孩子结点
int f=HuffNode[pos].parent;
while(f!=-1){
if(HuffNode[f].lchild==pos){
temp[--start]='0'; //是左孩子编码0
}
else{
temp[--start]='1'; //是右孩子编码1
}
pos=f;//更新pos结点,移动到它的父亲
f=HuffNode[pos].parent;//更新父结点
}
huffCode[i]=new char[n-start];//建立哈夫曼编码实际需要的内存空间
strcpy(huffCode[i],&temp[start]);//将哈夫曼编码存储到huffCode中
}
delete temp;//释放存储空间
}
运行结果如下:
这个代码经过试验,可以完整运行,至于算法的详细讲解,可以去B站看“懒猫老师”的视频哦,视频中的图解可帮助快速理解算法原理。
【懒猫老师-数据结构-(34)哈夫曼树(Huffman Tree,霍夫曼树,赫夫曼树)-哔哩哔哩】
【懒猫老师-数据结构-(35)哈夫曼编码1(Huffman coding,霍夫曼编码,赫夫曼编码)-哔哩哔哩】