构建哈夫曼树压缩 java_java实现哈夫曼树进行文件加解压

1.哈夫曼树简述

给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。

为什么使用哈夫曼编码压缩文件?

一个字符八个bits,若使用编码来表示字母,节省空间,传输速度快。根据字母出现的频率构建哈夫曼树,频数即为权值,频数出现最多的字母更靠近哈夫曼树的根节点,编码长度也更短。

13f9b1d81fec20229d2dee07ad40c604.png

ca81cc5d6635fc1aec7f498ebcc5d228.png

2.构造树的节点

先构造一个哈夫曼树的节点类,节点类包含5个元素:指向左节点、右节点的指针、代表的字母、频数和对应编码。

private HaffNode left,right;

private char ch;

private int n;

private String code;

复写节点类的compareTo方法,方便排序。

//便于使用列表排序

@Override

public int compareTo(Object o) {

HaffNode a=(HaffNode)o;

if(this.n>a.n)

return 1;

else if(this.n==a.n)

return 0;

else

return -1;

}

3.构造哈夫曼树的类(压缩)

构造一个哈夫曼树类,类中有6个元素:包含26个字母和空格的字符数组、读取文件得到的字符数组、保存各个节点权值的整数数组、哈夫曼树的根节点,哈夫曼树的列表形式,以及保存各个节点编码值的字符串数组。

//创立字母表

private static char[] ch={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',' '};

//文件内容的字符数组

private char[] a=new char[100];

//各个字符的频数

private int[] sum=new int[27];

//树的根节点

private HaffNode root;

//保存压缩文件的单个编码

private String[] strings=new String[28];

//哈夫曼树的列表形式

private LinkedList treelist=new LinkedList();

读取未压缩文件

//从文件中读取字节流,并保存为字符数组

public void read(String path,String name) throws IOException {

int i=0;

File f=new File(path,name);

Reader reader=new FileReader(f);

while(reader.ready()){

a[i++]=(char)reader.read();

}

reader.close();

System.out.print("压缩前的文件内容为:");

for(int k=0;k

System.out.print(a[k]);

}

System.out.println();

}

进行频数统计

//统计各个字母的频次

public void count(){

for(int k=0;k

for (int j=0;j

if(a[k]==ch[j])

sum[j]++;

}

}

}

构造一棵哈夫曼树,将所有节点都加入列表后先排序一次。当列表长度大于1时,每次选取两个列表中权值最小的节点(也就是列表第1位和第2位的节点),构成一个字符为空的父节点,列表中删除这两个节点,把父节点加入列表后,对列表再次排序,循环到列表中只剩下一个节点时,该节点为根节点,保存。

//构造哈夫曼树,保存树的根节点

public LinkedList createTree() {

count();

//匹配频数和字符构成节点,全部加入树的列表

for (int i = 0; i < 27; i++) {

HaffNode node = new HaffNode();

node.setCh(ch[i]);

node.setN(sum[i]);

treelist.add(i, node);

}

Collections.sort(treelist);

while (treelist.size() > 1) {

//获得两个权值最小的节点

HaffNode first = (HaffNode) treelist.removeFirst();

HaffNode second = (HaffNode) treelist.removeFirst();

//将这两个权值最小的节点构造成父节点

HaffNode parent = new HaffNode();

parent.setN(first.getN() + second.getN());

parent.setLeft(first);

parent.setRight(second);

//把父节点添加进列表,并重新排序

treelist.add(parent);

Collections.sort(treelist);

}

root= (HaffNode) treelist.getFirst();

}

根据哈夫曼树获取编码:左子树编码为0,右子树编码为1

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值