当前位置:文档之家› (在VC++上调试通过)哈夫曼树编码上机实验

(在VC++上调试通过)哈夫曼树编码上机实验

//注意:在输入n个权值时,每输入一个权值都要按一个回车键
#include"iostream"
#include"stdlib.h"
#include"stdio.h"
#include"malloc.h"
#include"string.h"
using namespace std;
#define UNIT_MAX 65535
typedef struct TNode
{ int parent;
unsigned int weight;
unsigned int lchild;
unsigned int rchild;
} *HuffmanTree, HTNode;
typedef char **HuffmanCode;
int select(HuffmanTree t, int i)//返回根节点中权值最小的树的根节点的序号函数select()调用{
int j;
int find=0;
int k = UNIT_MAX;//取K为不小于可能的值
for (j = 1; j < i; j++) //在t数组的前i-1个数组元素中寻找一个parent值为0且权值最小的if ((int)t[j].weight < k && t[j].parent == 0)
{
k = t[j].weight;
find=j;
}
t[find].parent = 1;
return find;
}
char** HuffmanCoding(HTNode HT[], char* HC[], int w[], int n)
{ //w存放n个字符的权值的一维数组,n为叶子个数;构造哈夫曼树HT;HC数组用以存放求得的n个字符的编码
int m, i, s1, s2, start;
int c, f;
HuffmanTree p;
char* cd;
m = 2 * n - 1; //n即为叶子数n0,由二叉树性质,n0=n2+1,故树中结点数为*n-1
for (i = 1, p = HT + 1; i <= n; ++i, ++p, ++w)
{//n个叶子结点赋初值,n个叶子最初为n个根结点,p指向HT[1],HT[0]不用(*p).weight = *w;
(*p).parent = 0;
(*p).lchild = 0;
(*p).rchild = 0;
}
for (i=n+1; i <= m; i++, p++) //n-1个附加的父亲结点赋初值
{
(*p).weight = 0;
(*p).parent = 0;
(*p).lchild = 0;
(*p).rchild = 0;
}
for (i = n + 1; i <= m; i++) // 第i次循环时为第i个结点选择两个儿子结点s1与s2 { s1 = select(HT,i); // 在i-1棵子树中也即HT[1..i-1]中选择无父亲(parent为0)且权值最小
s2 = select(HT,i); //的两个结点(其序号分别为s1和s2)。

HT[i].weight = HT[s1].weight + HT[s2].weight;//i结点为s1结点和s2结点的父亲结点
HT[i].lchild = s1; //建立左儿子关系
HT[i].rchild = s2; //建立右儿子关系
HT[s1].parent = HT[s2].parent = i;//建立父亲关系
}
//哈夫曼树HT构造完毕
cd = (char*)malloc(n * sizeof(char)); // 申请存放编码的工作数组(n个字符空间) cd[n - 1] = '\0'; // 当前字符的编码工作数组的最后一个单元存放一个结束符。

for (i = 1; i <= n; ++i)
{ //第i次循环时求第i个叶子(字符)的哈夫曼编码
start = n - 1; // start指向cd数组(即工作数组)中编码结束符的位置
for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
{ // 从叶子到根逆向求编码
start--;
if (HT[f].lchild == c) cd[start] = '0'; //若当前结点是其父亲的左孩子,赋值'0'
else cd[start] = '1'; //若当前结点是其父亲的右孩子,则赋值'1'
}
HC[i] = (char*)malloc(n* sizeof(char)); //为存放第i个字符的编码申请空间
strcpy(HC[i], &cd[start]); //从cd复制编码(串)到HC,函数strcpy在头文件string.h中}// i从1到n求n个叶子的编码结束
return HC; //求编码结束,释放工作数组cd所占用的存储空间,将HC数组作为结果返回}// char** HuffmanCoding结束
void main()
{
HTNode *HT;
char** HC;
int* w, n, i;
printf("输入叶子节点个数:\n");
scanf("%d", &n);
if (n <= 1) return;
printf("输入各个叶节点所对应的权值, 每输入一个权值都要按一个回车键:\n");
w = (int*)malloc(n * sizeof(int));
HT = (HuffmanTree)malloc((2*n-1) * sizeof(HTNode));// 0号单元未用
HC = (HuffmanCode)malloc((n+1) * sizeof(char*));// 0号单元未用
for (i = 0; i < n ; i++)
scanf("%d",&w[i]); //每输入一个值按一个回车键
HuffmanCoding(HT, HC, w, n);
cout<<n<<"个叶子的编码为:\n";
for(i=1;i<=n;i++)
{ //打印n个字符的编码
printf("%s\n",HC[i]);
}
}//main结束
输出结果:。

相关主题