不难- -! 哈夫曼树...
编译没有错误!但是结果不是正确的!也就是哈夫曼树编码错误!
例:输入结点为3
权值为1 2 3
结果输出:
1(1):10
2(2):11
3(3):0
个人觉得是:
1(1):00
2(2):01
3(3):1
望高手指点!谢谢~
//根据给定的结点和权值,构建哈夫曼树,并进行哈夫曼编码
例:输入结点为3
权值为1 2 3
结果输出:
1(1):10
2(2):11
3(3):0
个人觉得是:
1(1):00
2(2):01
3(3):1
望高手指点!谢谢~
//根据给定的结点和权值,构建哈夫曼树,并进行哈夫曼编码
#include <stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#define OVERFLOW -2
#define OK 1
int m,s1,s2;
typedef struct
{
unsigned int weight;//权值
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树
typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码表
void Select(HuffmanTree HT,int n)//在数组中寻找权值最小的两个结点
{
int i,j;
for(i = 1;i <= n;i++)
if(!HT[i].parent)
{
s1 = i;break;
}
for(j = i+1;j <= n;j++)
if(!HT[j].parent)
{
s2 = j;break;
}
for(i = 1;i <= n;i++)
{ if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i))
s1=i;}
for(j = 1;j <= n;j++)
{if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j))
s2=j;}
}
void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int n)
{ // 算法6.13
// w存放n个字符的权值(均>0),构造哈夫曼树HT,
// 并求出n个字符的哈夫曼编码HC
int i,j;
char *cd;
int p,cdlen;
if (n<=1) exit(OVERFLOW);//return ;
m = 2 * n - 1; //总节点个数
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用
for (i=1; i<=n; i++)
{ //初始化
HT[i].weight=w[i-1];
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=n+1; i<=m; i++)
{ //初始化
HT[i].weight=0;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
puts("\n哈夫曼树的构造过程如下所示:");
printf("HT初态:\n 结点 weight parent lchild rchild");
for (i=1; i<=m; i++)
printf("\n%4d %8d %8d %8d %8d",i,HT[i].weight,HT[i].parent,HT[i].lchild, HT[i].rchild);
printf(" 按任意键,继续选择...");
getchar();
for (i=n+1; i<=m; i++)
{ // 建哈夫曼树
// 在HT[1..i-1]中选择parent为0且weight最小的两个结点,
// 其序号分别为s1和s2。
Select(HT, i-1);
HT[s1].parent = i; HT[s2].parent = i; //修改s1和s2结点的父指针parent
HT[i].lchild = s1; HT[i].rchild = s2; //修改i结点的左右孩子指针
HT[i].weight = HT[s1].weight + HT[s2].weight; //修改权值
printf("\nselect: s1=%d s2=%d\n", s1, s2);
printf(" 结点 weight parent lchild rchild");
for (j=1; j<=i; j++)
printf("\n%4d %8d %8d %8d %8d",j,HT[j].weight,
HT[j].parent,HT[j].lchild, HT[j].rchild);
printf(" 按任意键,继续选择...");
getchar();
}
//------无栈非递归遍历哈夫曼树,求哈夫曼编码
cd = (char *)malloc(n*sizeof(char)); //开辟一个求编码的工作空间
p = m; cdlen = 0;
for (i=1; i<=m; ++i) // 遍历哈夫曼树时用作结点状态标志
HT[i].weight = 0;
while (p)
{
if (HT[p].weight==0)
{ // 向左
HT[p].weight = 1;
if (HT[p].lchild != 0){p = HT[p].lchild; cd[cdlen++] ='0';} //若是左孩子编为'0'
else if (HT[p].rchild == 0)
{ // 登记叶子结点的字符的编码
HC[p] = (char *)malloc((cdlen+1) * sizeof(char)); //为第p个编码分配空间
cd[cdlen] ='\0';//编码结束符
strcpy(HC[p], cd); //将编码从cd复制到HC中
}
}
else if (HT[p].weight==1)
{ // 向右
HT[p].weight = 2;
if (HT[p].rchild != 0) { p = HT[p].rchild; cd[cdlen++] ='1'; }//若是右孩子编为'1'
}
else
{ // HT[p].weight==2,退回退到父结点,编码长度减1
HT[p].weight = 0;
p = HT[p].parent;
--cdlen;
}
}
} // HuffmanCoding
int main()
{
HuffmanTree HT;//哈夫曼树HT
HuffmanCode *HC;//哈夫曼编码表HC
int *w,n,i; //w存放叶子结点权值
printf("输入结点数:");//puts("输入结点数:");
scanf("%d",&n);
HC = (HuffmanCode *)malloc(n*sizeof(HuffmanCode)); //分配n个编码的头指针向量
w = (int *)malloc(n*sizeof(int));
printf("输入%d个结点的权值\n",n);
for(i = 0;i < n;i++)
{
scanf("%d",&w[i]);
}
HuffmanCoding(HT,HC,w,n);
puts("\n各结点的哈夫曼编码:");
for(i = 1;i <= n;i++)
printf("%2d(%2d):%s\n",i,w[i-1],HC[i]);
getchar();
}
...全文
相关推荐
哈夫曼树的建立(根据输入的权值,建立一棵哈夫曼树)
根据输入的权值建立一棵哈夫曼树,并显示该树的结点序号、双亲结点、左/右孩子结点以及各结点所对应的哈夫曼编码。
哈夫曼树及哈夫曼编码数据结构实验报告
构建哈夫曼树,对其进行编码,实现译码功能,数据结构的实验报告。。
C++实现哈夫曼树及哈夫曼编码.rar
C++实现哈夫曼树及哈夫曼编码,代码简介https://blog.csdn.net/qq_41664447/article/details/90736442,C++源程序可直接运行
哈夫曼树及哈夫曼编码译码的实现
问题描述:利用哈夫曼编码进行信息通讯可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传输数据预先编码;在接受端将传来的数据进行译码。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站编写一个哈夫曼码的编/译码系统。 基本要求:根据某字符文件统计字符出现频度,构造Huffman 树,编制Huffman编码,并将给定字符文件编码,生成编码文件;再将给定编码文件解码,生成字符文件。(要求按二进制位表示编码) 提高要求:改进Huffman编码,产生两种以上的编码方案,对同一组测试数据,用不同的编码方案编码,从文件长度、算法复杂度等方面进行比较。 测试数据:英文文档文件或中文文档文件。
三元哈夫曼编码 哈夫曼树
详细描述了哈夫曼树的构造方法,同时推广到三元哈夫曼编码,并用C语言于VC++上实现


