c++代码实现:
// MyTest.cpp : 定义控制台应用程序的入口点。
/*哈夫曼构建
思想是弄成一个结构体数组,结构体数据本身就具备了表的特征
*/
#include "stdafx.h"
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
#define MAXBIT 100
#define MAXVALUE 10000
#define MAXLEAL 6
#define MAXNODE MAXLEAL*2-1
typedef struct{
double weight;//权值
int parent;//父节点
int lchild;//左孩子
int rchild;//右孩子
char value;//该节点表示的字符
}HNodeType;
typedef struct{
int bit[MAXBIT];//存储编码的数组
int start;//编码开始下标
}HCodeType;//编码结构体
HNodeType HuffNode[MAXNODE];//定义一个结构体节点数组
HCodeType HuffCode[MAXLEAL];//定义一个编码结体体数组
/*构建啥夫曼编码*/
void HuffManTree(HNodeType HuffNode[MAXNODE], int n){
/*i,j两个循环变量;x1,x2两个最小权值结点在数组中的序号*/
int x1, x2;
double m1, m2;
/*初始化哈夫曼树数组huffmanNode[]中的结点*/
for (int i = 0; i < 2 * n - 1; i++){
HuffNode[i].weight = 0;
HuffNode[i].parent = -1;
HuffNode[i].lchild = -1;
HuffNode[i].rchild = -1;
}
/*输入n个叶子结点的权值*/
for (int i = 0; i < n; i++){
cout << "please input the weight and value of huffman" << i + 1 << endl;
cin >> HuffNode[i].weight >> HuffNode[i].value;
}
//构造huffman树
for (int i = 0; i < n - 1; i++){
//执行n-1次合并
m1 = m2 = MAXVALUE;
/*m1,m2存放两个无父节点,且节点值最小的两个数*/
x1 = x2 = 0;
for (int j = 0; j < n + i; j++){
if (HuffNode[j].weight < m1&&HuffNode[j].parent == -1){
//比第一个数权值小的时候
m2 = m1;//m2存次小的数权值
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[x1].parent = n + i;
HuffNode[x2].parent = n + i;
HuffNode[n + i].weight = m1 + m2;
HuffNode[n + i].lchild = x1;
HuffNode[n + i].rchild = x2;
cout << "the x1.weight and x2.weight in round" << i + 1 << "\t" << HuffNode[x1].weight <<"\t"<< HuffNode[x2].weight << endl;
}
}
/*哈夫曼编码*/
void HuffmanCode(HCodeType HuffCode[MAXLEAL], int n){
HCodeType cd;//定义一个变量用来求解解码时的信息
int c, p;
for (int i = 0; i < n; i++){
cd.start = n - 1;
c = i;//因为在构建哈夫曼树时,是从最小两个权值找起的,所以i=0一定是叶子结点
p = HuffNode[c].parent;
while (p != -1){
if (HuffNode[p].lchild == c)cd.bit[cd.start] = 0;
else cd.bit[cd.start] = 1;
cd.start--;//求编码的低一位
c = p;//往上移,看父节点的左孩子是不是与C(代表此时的节点)相等
p = HuffNode[c].parent;//设置下一个循环条件
}
/*把叶子结点的编码信息从临时的cd中复制出来,放入数据结构体来*/
for (int j = cd.start + 1; j < n; j++)
HuffCode[i].bit[j] = cd.bit[j];
HuffCode[i].start = cd.start;//每次编码记录下cd.start的值
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int n;
cout << "please input n:" << endl;
cin >> n;
HuffManTree(HuffNode, n);/*构造哈夫曼树*/
HuffmanCode(HuffCode, n);/*哈夫曼编码*/
/*输出已经保存好的所有哈夫曼编码*/
for (int i = 0; i < n; i++){
cout << HuffNode[i].value << ":Haffman code is: ";
for (int j = HuffCode[i].start + 1; j < n; j++)
cout << HuffCode[i].bit[j];
cout << endl;
}
return 0;
}
C代码实现:
// MyTest.cpp : 定义控制台应用程序的入口点。
/*哈夫曼构建
思想是弄成一个结构体数组,结构体数据本身就具备了表的特征
*/
#include "stdafx.h"
#include <stdio.h>
#pragma warning(disable:4996)
#define MAXNODE 100
#define MAXTREEHIGH 30
#define MAXVALUE 1000//先定义一个最大值,以找出哈夫曼树组的两个最小值
typedef struct{
double weight;//权值
int parent;
int lchild;
int rchild;
char value;
}HNodeType;//节点信息抽象
typedef struct{
int bit[MAXNODE];
int start;
}HCodeType;//编码,每个节点对应一个编码
HNodeType HuffNode[MAXNODE];/*定义结点数组,形成一个结点信息表*/
HCodeType HuffCode[MAXTREEHIGH];/*定义哈夫曼树高,以编码*/
/*构建哈夫曼树*/
void BiludeHaffmanTree(HNodeType HuffNode[MAXNODE], int n){
int x1, x2;//两个最小权值的数组的序号
double m1, m2;//两个最小权值的值
/*找出所有结点中权值最小、无父结点的两个结点,并合并为一棵二叉树*/
for (int i = 0; i < 2 * n - 1; i++){//n个叶子节点的二叉树,则有2n-1的结点
HuffNode[i].weight = 0;
HuffNode[i].parent = -1;
HuffNode[i].lchild = -1;
HuffNode[i].rchild = -1;
}
/*输入叶子结点的权值*/
for (int i = 0; i < n; i++){
printf("Please input value and weight of lead node:%d\n", i + 1);
scanf(" %c%lf", &HuffNode[i].value, &HuffNode[i].weight);//这里double类型的输入,这里出错,调了很长时间
//scanf(" %lf", &HuffNode[i].weight);
//scanf("%f%c", &HuffNode[i].weight, &HuffNode[i].value );
}
//开始构建
for (int i = 0; i < n - 1; i++){
m1 = m2 = MAXVALUE;
x1 = x2 = 0;
for (int j = 0; j < n + i; j++){//从哈夫曼数组中找,n+i为存储两个最小权值加值
//不用担心同样值的构造出来的权值与原数组中值相同,因为构造出来权值在后面
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[x1].parent = n + i;
HuffNode[x2].parent = n + i;
HuffNode[n + i].weight = m1 + m2;
HuffNode[n + i].lchild = x1;
HuffNode[n + i].rchild = x2;
printf("x1.weight and x2.weight in round %d:\t%.3f\t%.3f\n", i + 1,HuffNode[x1].weight,HuffNode[x2].weight);
}
}
/*哈夫曼编码*/
void BiludHaffmanCode(HCodeType HuffCode[MAXTREEHIGH], int n){
HCodeType cd;/*定义一个编码的临时变量*/
int c, p;//p代表父节点
for (int i = 0; i < n; i++){
cd.start = n - 1;
c = i;
p = HuffNode[c].parent;
while (p != -1){
if (HuffNode[p].lchild == c)
cd.bit[cd.start] = 0;
else
cd.bit[cd.start] = 1;
cd.start--;
c = p;
p = HuffNode[c].parent;
}
/*把叶子结点编码信息从临时编码cd中复制出来,放入编码结构体数组中*/
for (int j = cd.start + 1; j < n; j++)
HuffCode[i].bit[j] = cd.bit[j];
HuffCode[i].start = cd.start;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int n;
printf("Please input the n: ");
scanf("%d", &n);
BiludeHaffmanTree(HuffNode, n);
BiludHaffmanCode(HuffCode, n);
for (int i = 0; i < n; i++){
printf("%c :Huffmancode is :", HuffNode[i].value);
for (int j = HuffCode[i].start + 1; j < n; j++)
printf("%d", HuffCode[i].bit[j]);
printf("\n");
}
return 0;
}