我写的是一个哈夫曼编码的程序,检查了很久了还没找到提示出错的原因 :( 系统提示出错的具体语句后面我都打了 *** 号。 检查了其他的地方,都是正确的,哈夫曼树建立成功了,就下面通过树编码的方法出了问题。哈夫曼树的叶节点存储了每个字符和它出现的频率,并且离根节点越近的字符频率越大。 doCoding 方法初始化一组存放编码结果的 Result 类并且调用 Coding 方法进行编码。Coding 采用了递归的方法进行编码。还有一些具体的注视我写在程序里了 :) public static void doCoding( root )
{
int m=a.total; //a.total 是总共出现了多少种字符
codeResult=new Result[ m ]; //Result是自建的存储一个字符的编码的类,包
含一个insert方法来插入0或1两个数字,分别代表
for(int k=0; k<m ;k++) 根节点到叶节点路径的向左拐和向右拐
codeResult[k]=new Result(); //
coding( root ); ***
}
public static void coding(Node current) {
if( current != null)
{
if(current.leftChild==null && current.rightChild==null) //到达叶节点
{
while( current.parent!=null ) //未到达根节点
{
if(current==current.parent.leftChild) //向左拐则插入0
codeResult[ codeNum ].insert(0); *** //codeNum是一个全局变量,
初始为0
else //向右拐则插入1
codeResult[ codeNum ].insert(1);
current=current.parent; //当前指针向上一位
}
codeNum++;
}
coding( current.leftChild ); *** //递归
coding( current.rightChild );
}
程序有点乱 有什么地方没看明白请一定向我提问 我都郁闷了好几天啦!
{
int m=a.total; //a.total 是总共出现了多少种字符
codeResult=new Result[ m ]; //Result是自建的存储一个字符的编码的类,包
含一个insert方法来插入0或1两个数字,分别代表
for(int k=0; k<m ;k++) 根节点到叶节点路径的向左拐和向右拐
codeResult[k]=new Result(); //
coding( root ); ***
}
public static void coding(Node current) {
if( current != null)
{
if(current.leftChild==null && current.rightChild==null) //到达叶节点
{
while( current.parent!=null ) //未到达根节点
{
if(current==current.parent.leftChild) //向左拐则插入0
codeResult[ codeNum ].insert(0); *** //codeNum是一个全局变量,
初始为0
else //向右拐则插入1
codeResult[ codeNum ].insert(1);
current=current.parent; //当前指针向上一位
}
codeNum++;
}
coding( current.leftChild ); *** //递归
coding( current.rightChild );
}
程序有点乱 有什么地方没看明白请一定向我提问 我都郁闷了好几天啦!
帮不了你,我只知道那个错误是溢出错误,一般这种问题好像都是出在数组中,多是调用了不存在的数组位而出现,嘿嘿,乱猜~~~
检查codeNum的值..数组下标从0开始..
codeResult[ codeNum ].insert(0); *** //codeNum是一个全局变量,
初始为0
else //向右拐则插入1
codeResult[ codeNum ].insert(1);
改成:
if(codeNum < 0 || codeNum >= codeResult.length)
System.out.println("codeNum="+codeNum+" other debug information ="+.....);
codeResult[codeNum].insert((current==current.parent.leftChild)?0:1);
另外ArrayIndexOutOfBoundsException会告诉你什么位置越界了
{
while( current.parent!=null ) //假设这里为条件2
{
if(current==current.parent.leftChild) //假设这里为条件3
codeResult[ codeNum ].insert(0);
else //假设这里为条件4
codeResult[ codeNum ].insert(1);
current=current.parent; //当前指针向上一位
}
codeNum++;
}
coding( current.leftChild ); //递归1
coding( current.rightChild ); //递归2
假设你的树只有1个根节点和1个左叶结点,那么,第一次函数,因为是从根结点开始进函数的,所以一开始假设条件1,2,3,4是不会执行的,直接执行到递归1,我们姑且把这次递归叫做[第一次来到递归1],这时递归1进入函数后,首先开始来到假设条件1,满足,继续判断条件2,满足,继续判断条件3,满足,继续执行,来到[当前指针向上一位]处,又找到了根结点,然后继续循环,不满足循环条件,退出,继续执行,又来到递归1,我们姑且把这次递归叫做[第二次来到递归1],这时递归1又进入函数,到此,有没有发现,这和[第一次来到递归1]是否没区别,就这样不断的没尽头的执行,数组当然就越界了
再仔细看一下你的程序,我看你好像没有贴全,至少少一个括号,是在current==null时退出吗?
1
2 3
4 5 6 7coding(4)
-->current=2
-->current=1
coding(2)--->coding(4)???? then coding(5)
coding(3)--->coding(6) then coding(7)
???
static int codeNum;
public static void doCoding(Node localRoot)
{
System.out.println("There are "+a.total+" kinds of char" );
codeResult=new Result[ a.total ];
for(int k=0; k<a.total ;k++)
codeResult[k]=new Result();
codeNum=0;
coding( localRoot );
}
public static void coding(Node current){ if( current != null)
{
if(current.leftChild==null && current.rightChild==null)
{
codeResult[codeNum].ch=current.ch;
while( current.parent!=null )
{
if(codeNum < 0 || codeNum >= a.total)
{
System.out.println("codeNum="+codeNum+" other debug information =");
codeResult[codeNum-2].display();
}
codeResult[codeNum].insert((current==current.parent.leftChild)?"0":"1");
current=current.parent;
}
codeNum++;
}
coding( current.leftChild );
coding( current.rightChild );
}
}
和上面这一节有关的类 :
public class Result {
public String code;
public char ch; public void insert(String dd)
{
code=code+dd;
}
public void display()
{
System.out.print(ch + ": ");
System.out.println( code );
}
}我改写所根据的那个遍历的源程序(前序遍历):
private void preOrder(Node localRoot)
{
if(localRoot != null)
{
System.out.print(localRoot.iData + " ");
preOrder(localRoot.leftChild);
preOrder(localRoot.rightChild);
}
}
准备一小段文字,自己想想应该是怎么做coding的,然后运行你的程序,看结果是不是如你所想.
程序修改如下:
public static void coding(Node current) {
System.out.println("debug: coding("+current.ch+"...)");
if (current != null) return; // do nothing
if (current.isLeaf()) {
codeResult[codeNum].ch = current.ch;
while (current.parent != null) {
if (codeNum < 0 || codeNum >= a.total) {
System.out.println("codeNum=" + codeNum +
" other debug information =");
codeResult[codeNum - 2].display();
System.exit(-1);
}
codeResult[codeNum].insert(current.isLeftChild() ? "0" : "1");
current = current.parent;
}
codeNum++;
}
coding(current.leftChild);
coding(current.rightChild);
}
}
public static void coding(Node current) {
System.out.println("debug: coding("+((current==null)?"null":""+current.ch)+"...)");
if (current == null) return; // do nothing
...