哈夫曼树即为最小二叉树,也叫最优二叉树。
哈夫曼编码是在此基础上产生,能够大幅提高编码效率。
编写一个能够生成哈夫曼编码的程序,是对数据结构初学者的基本要求。
首先是树结构。我设计的树节点结构包括元素sign(放符号),weight(放权值),parent(父亲节点),lchild(左儿子节点),rchild(右儿子节点),flag(用于标记是否被放入树中的标示。)
需手动输入符号和他们各自的权值,以及叶子节点(符号总数)
算法设计思想:
n个叶子节点,则一共2n-1个树节点。初始化先。
将他们的信息存放至树节点中。注意有下标,下标为1到n,对应录入顺序的数据。不用下标感觉会很麻烦。因为树结构的父子元素都是用整形数据(即他们的下标)存的,没有用指针。
首先比较权值大小,选出众叶子节点中最小的两个元素,将他们的权值由小到大分别存放至m1,m2.用x1,x2存放他们的下标。下标是他们区别对方标示自己的唯一标记。由上可知均是整型变量,临时保存。
then,将权值相加,存到第n+1个树节点的weight中,然后记得将那两个儿子的flag标记为已经加入到树中,同时存parent,lchild,rchild等值。这里重点在于通过循环逐一实现。
我用for循环,循环了n-1次,(n+n-1才等于2n-1)。没1论循环,少两个节点,多一个节点。早最后一轮,应该只有两个节点。要注意flag。
子循环是for(j=i;j<n+i;j++),里面同时注意if flag没被标示才进行比较。//这里错了!!应该是for(j=1,不能让循环的轮数少比较了参数!!)
父循环是for(i=1;i<=n-1;i++)
这里的i,j直接和下标挂钩。注意不要出错。
循环结束后,2n-1个节点里面都有值了,哈夫曼树也生成了。
我继续在该函数中,把编码的功能也加进去了,因为省事。(主要还是直接用他们存好的下标)
父循环n次,n个叶子节点。
子循环,从下标1的开始一直到n。用int m存储他的父亲信息,然后找到它父亲,看他的下标是等于他父亲的左儿子还是右儿子。根据情况往整形数组里面存数据1,0直到到达根节点为止。然后把数组倒序输出,就是这个叶节点的哈夫曼编码。
写完后有错误,是函数格式定义错误。。。。
然后发现 struct 和 typedef struct还是有不同的:
在C语言里,后面再详细说。最后的解决方法是,在结构体尾部加了一个变量类型。(前面的一个是标示符,后面的一个是变量类型)。
int bit[10]=0,出错!最后改为{0},解除。
问题又出现了:HaffNode[i].sign=sign[i]; 这句话他说sign是未声明的变量……
找到问题,忘了在函数的声明之中放敏感变量char sign[]。……还有就是C++中慎用/*.....*/也容易报错!
然后报错的LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16
出现这个错误的原因是你创建了win32 Application工程,而主函数却定义为了控制台模式的main函数。
第一种:重新创建一个Win32 Console Application工程,或不创建工程直接添加C++ Source File,将代码拷贝过去;
第二种:在工程->设置->连接 的工程选项里找到/subsystem:windows 改成/subsystem:console就可以了。
终于无措可以运行了结果特么的输入完权值后直接未响应,真绝望啊!以之前的经验,估计又是指针的问题,猜的……出现段错误!!大概是因为结构体指针没有给它赋值。
搞复杂了,,不是前面的问题,而是循环里面当初不知为啥多加了一组大括号。。。
程序可以执行,但是出来的哈夫曼编码有错误!!继续调试。貌似是if中判断是否等于时亡用“==”了。然后又是发现循环里面的一个参数弄错了,改了之后
终于输出正确的哈夫曼编码!!
但是为啥还是有段错误!!
可能是指针没有释放!!晚上在研究!!
关于C++中,new和delete;
new运算符使用的一般格式为 new 类型 [初值] 用new分配数组空间时不能指定初值。如果由于内存不足等原因而无法正常分配空间,则new会返回一个空指针NULL,用户可以根据该指针的值判断分配空间是否成功。 delete运算符使用的一般格式为 delete [ ] 指针变量 例如要撤销上面用new开辟的存放单精度数的空间(上面第5个例子),应该用 delete p; 前面用“new char[10];”开辟的字符数组空间,如果把new返回的指针赋给了指针变量pt,则应该用以下形式的delete运算符撤销该空间: delete [] pt;//在指针变量前面加一对方括号,表示是对数组空间的操作 。
错误解决!原因就是因为产生了野指针!原来我的哈夫曼函数是Haffman(weight,sign,n,myHaff);其中myHaff是一个指针,指向了一片HaffTreeNode型的空间,但是,
我定义的函数是void Haffman(int weight[],char sign[],int n,HaffTreeNode HaffNode[])
声明中没有用到指针变量,HaffTreeNode只是变量类型。而且函数当中也没有用到指针。所以当函数运行完之后,返回到调用语句时,不能返回一个指针变量。所以,出现未响应,或者是debug error或者debug assertion failed(野指针)
哈夫曼树完毕。指针这块果然还是避而远之为妙。日后可能改行去搞java。