第六周作业2——哈夫曼编码实现

哈夫曼编码的实现

     对教材P167中习题5.18,编码实现哈夫曼编码树,并对“Chapter Graphs surveys the most important graph processing problems  including depth-first search breadth first search minimum spanning trees and shortest paths ”语句使用构造的哈夫曼编码进行压缩(不区分大小写),对压缩后的数据进行解压缩。

    构建节点类

public class BTNode {
	 private char key;
	    private BTNode left, right;
	    private int weight;

	    public BTNode(char key,int weight) {
	        this(key,weight,null, null);
	    }

	    public BTNode(char key,int weight, BTNode left, BTNode right) {
	        this.key = key;
	        this.weight=weight;
	        this.left = left;
	        this.right = right;
	    }

	    public char getKey() {
	        return key;
	    }

	    public void setKey(char key) {
	        this.key = key;
	    }
	    
	    public int getWeight(){
	    	return weight;
	    }
	    
	    public void setWeight(int weight){
	    	this.weight=weight;
	    }
	    public BTNode getLeft() {
	        return left;
	    }

	    public void setLeft(BTNode left) {
	        this.left = left;
	    }

	    public BTNode getRight() {
	        return right;
	    }

	    public void setRight(BTNode right) {
	        this.right = right;
	    }
}
   

 构建哈夫曼树,进行哈夫曼编码


public class BinTree {
	protected BTNode root;
	public static int lif=0,rig=0;
	public static long hfbm[][]=new long[27][12];  //用于存放字母对应的哈夫曼编码
	public static char af[]=new char[27];     //存放前序遍历哈夫曼树的顺序字母,af[i]与hfbm[i][]对应
    public BinTree(BTNode root) {
        this.root = root;
    }

    public BTNode getRoot() {
        return root;
    }

    /** 构造树 */
    public static void init() {
    	int wt[]={183,102,77,68,59,58,55,51,49,48,35,34,26,
    			24,21,19,18,17,16,16,13,9,6,2,2,1,1};  //字母对应的频率转化为整数权值
    	int w[]=new int[53];    //定义数组w[]存放节点的权值
    	for(int i=0;i<w.length;i++)
    		w[i]=10000;       //初始化w[]
    	for(int j=0;j<wt.length;j++)
    		w[j]=wt[j];       
    	char s[]={' ','e','t','a','o','i','n','s','h','r','d','l','c',
    			'u','m','w','f','g','y','p','b','v','k','j','x','q','z'};
    	BTNode hf[]=new BTNode[53];  //建立53个节点用于构造哈夫曼树
    	BTNode root=new BTNode('T',0); //初始化根节点
    	for(int j=0;j<hf.length;j++){
    		hf[j]=new BTNode('*',0);   //初始化所有节点,节点字符为“*”,权值为0,左右子树为空
    	}
    	
    	for(int i=0;i<27;i++){    //将27个字符放入对应的节点中,并赋予权值
    		hf[i].setKey(s[i]);
    		hf[i].setWeight(wt[i]);
    	}
    	// 构造哈夫曼树
    	int i1=0,i2=0,lin=0;
    	for(int k=27;k<53;k++){
    		i1=select(w); //搜索w[]中最小的值,并将对应的序号值赋予i1
    		lin=w[i1];
    		w[i1]=10000; //w[]中的i1的值,使之退出下一次搜索
    		hf[k].setLeft(hf[i1]);
    		i2=select(w); //搜索w[]中最小的值,并将对应的序号值赋予i2
    		lin=lin+w[i2];
    		hf[k].setRight(hf[i2]);
    		hf[k].setWeight(lin); //将i1,i2的权值之和存入hf[i1],hf[i2]的父节点中
    		w[i2]=10000;
    		w[k]=lin;   //w[]中的i2的值,使之退出下一次搜索,将k的值加入下一次搜索
    		i1=0;i2=0;lin=0; //临时数据清零
    		root=hf[k]; 
    	}
    	preorder(root,10); //前序遍历哈夫曼树
    }
    
    public static void main(String args[]){
    	String s="chapter graphs surveys the most "
    			+"important graph processing problems"
    			+"including depth-first search breadth "
    			+"first search minimum spanning trees and shortest paths";
    	try{
    		for(int i=0;i<27;i++){
    			af[i]=' ';
    			for(int j=0;j<12;j++)
    				hfbm[i][j]=2;
    		}  //初始化 af[],hfbm[][]
    		init();
    		for(int i=0;i<27;i++){
    			System.out.print("   "+af[i]+": ");
    			for(int j=0;j<12;j++)
    				if(hfbm[i][j]!=2)
    					System.out.print(hfbm[i][j]);
    			if((i+1)%3==0)
    			   System.out.println();
    		}  //输出字母与对应的哈夫曼编码
    		changehf(s);
    	}catch(Exception e){
    		e.printStackTrace();
    	}
    }
    
    public static void changehf(String s){
    	char cs[]=s.toCharArray();
    	System.out.println("该字符串转化为零一代码的结果是:");
    	for(int i=0;i<cs.length;i++){
    		for(int j=0;j<af.length;j++)
    			if(cs[i]==af[j]){   //在af[]寻找与cs[i]相同的字母
    				for(int n=0;n<12;n++)
    					if(hfbm[j][n]!=2)//将对应的哈夫曼编码输出
    						System.out.print(hfbm[j][n]);
    			}
    		if((i+1)%10==0) //每输出9个字母的
    			System.out.println();
    	}
    }
    
    //搜索w[]中最小的值,并将对应的序号返回
    public static int select(int w[]){
    	int ts=w[0],i1=0;
    	for(int i=1;i<w.length;i++){
    		if(ts>w[i]){
    			ts=w[i];
    			i1=i;
    		}
    	}
    	return i1;
    }

    /** 访问节点 */
    public static void visit(BTNode p,long q) {
    	if(p.getKey()=='*') //对
    		System.out.print("");
    	else{
    		long temp=0; int b=11;
    		while(q>=100){   //计算字母的哈夫曼编码 并去除前缀10
    			temp=q%10;
    			q=q/10;
    			hfbm[lif][b]=temp; 
    			b=b-1;
    	     }
    		af[lif]=p.getKey();//将节点的字母存入与hfbm[lif][]对应的字符数组af[lif]中
    		lif=lif+1;
    		
    	}
    }

    /** 递归实现前序遍历 */
    protected static void preorder(BTNode p,long q) {
        if (p != null) {
            visit(p,q);
            preorder(p.getLeft(),q*10+1); //访问左子树 q后面增加一个1
            preorder(p.getRight(),q*10);  //访问左子树 q后面增加一个0

        }
    }
}

运行结果图



  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值