实现Huffman树的创建,统计输入的字符串的个数,每个字符的哈弗曼编码,以及整个字符的哈弗曼编码,并将编码转换成byte类型。
1.构建节点:
package Huffman;
public class Node implements Comparable{
private int weight;//权重
private int data;//数据
//private String code;
private Node leftNode;//左子树
private Node rightNode;//右子树
//向节点中传入权重和数据
public Node(int data,int weight) {
this.data = data;
this.weight = weight;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getData() {
return data;
}
public void setData(char data) {
this.data = data;
}
public Node getLeftNode() {
return leftNode;
}
public void setLeftNode(Node leftNode) {
this.leftNode = leftNode;
}
public Node getRightNode() {
return rightNode;
}
public void setRightNode(Node rightNode) {
this.rightNode = rightNode;
}
/**
* 构建一个比较两个对象大小的方法
*/
public int compareTo(Object o){
int k=0;
if(o instanceof Node){
Node node=(Node)o;
if(weight>node.weight){
k=1;
}
if(weight<node.weight){
k=-1;
}
if(weight==node.weight){
if(data>node.data){
k=1;
}
if(data<node.data){
k=-1;
}
}
}
return k;
}
}
2.构建Huffman树:
package Huffman;
import java.util.PriorityQueue;
public class hfmTree {
//定义一个存储编码的字符串型数组,长度为256
protected String[] SaveCode=new String[256];
protected Node root;//定义一个根节点
//定义一个数组记录该储存单元字符出现的次数,长度为256
private int[] ascii=new int[256];
private String str;
//构造函数,将储存了数据的数组传进来
public hfmTree(int[] a,String str){
this.ascii=a;
this.str=str;
}
/**
* 用ascii数组中的数据来创建哈弗曼树
*/
public void createhfmTree(){
//用优先队列,实例化一个优先队列
PriorityQueue<Node> queue=new PriorityQueue<Node>();
//将ascii中的数据储存到节点中,然后将节点添加到队列中
for(int i=0;i<ascii.length;i++){
if(ascii[i]!=0){
//实例化一个哈弗曼节点
Node node=new Node(i,ascii[i]);//i表示数据,ascii表示数据出现的次数(权重)
queue.add(node);//将节点添加到队列中
}
}
//优先队列将节点按照数据的出现次数weight大小来排序
while(queue.size()>1){
//获取队列中的头元素,并将其删除
Node node1=queue.poll();
Node node2=queue.poll();//获取并移除次队列
//实例化一个合并的节点
Node result=new Node(Math.max(node1.getData(), node2.getData()),node1.getWeight()+node2.getWeight());
result.setLeftNode(node1);
result.setRightNode(node2);
queue.add(result);//将合并节点添加到队列中
}
root=queue.peek();//获取根节点,但不移除此节点的头
}
/**
* @param node:根节点
* @param s:储存节点数据中哈弗曼编码(即01字符串)
* 生成哈弗曼编码(获取编码)
* 哈弗曼编码储存在String中的SaveCode数组中
*/
public void getBM(Node node,String s){
//node左节点不为空赋值为0,右节点不为空则赋值为1
if (node.getLeftNode()!=null){
getBM(node.getLeftNode(),s+"0");
}
if(node.getRightNode()!=null){
getBM(node.getRightNode(),s+"1");
}
if(node.getLeftNode()==null&&node.getRightNode()==null)//说明该节点为叶子节点
{
//输出哈弗曼编码
System.out.println("字符:"+(char)node.getData()+"的hfm编码为"+s);
//存储哈弗曼编码
SaveCode[node.getData()]=s;
}
}
/**
* 构造方法
* 将整个字符串的哈弗曼编码由01字符串转换成byte型
*/
public byte[] ChangeCode(){
String temp="";//用来临时存放哈弗曼编码
for(int i=0;i<str.length();i++){
temp=temp+this.SaveCode[str.charAt(i)];
}
int length=temp.length();
int zero=length%8;//zero表示要添加零的个数
//利用for循环在temp尾部添加zero个零
for(int i=0;i<zero;i++){
temp=temp+"0";
}
//定义一个byte型数组来储存转换之后的值
byte[] array=new byte[temp.length()/8];
for(int i=0;i<temp.length()/8;i++){
array[i]=(byte)(-Integer.parseInt(String.valueOf(temp.charAt(8*i)))*128+
Integer.parseInt(String.valueOf(temp.charAt(8*i+1)))*64+
Integer.parseInt(String.valueOf(temp.charAt(8*i+2)))*32+
Integer.parseInt(String.valueOf(temp.charAt(8*i+3)))*16+
Integer.parseInt(String.valueOf(temp.charAt(8*i+4)))*8+
Integer.parseInt(String.valueOf(temp.charAt(8*i+5)))*4+
Integer.parseInt(String.valueOf(temp.charAt(8*i+6)))*2+
Integer.parseInt(String.valueOf(temp.charAt(8*i+7)))*1);
}
return array;
}
}
3.定义主函数入口:
package Huffman;
import java.util.Scanner;
public class Shuzu {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("请输入一串字符串:");
//输入要转换的字符串(实例化一个浏览器对象)
Scanner scanner=new Scanner(System.in);
String s=scanner.next();
//将字符串存放到数组中
int [] array=new int [256];
for(int i=0;i<s.length();i++){
array[s.charAt(i)]++;
}
for(int i=0;i<array.length;i++){
if(array[i]!=0){
System.out.println(""+(char)i+array[i]);
}
}
//创建一个哈弗曼树对象,将数组和字符传入该对象
hfmTree tree=new hfmTree(array,s);
//构建哈弗曼树
tree.createhfmTree();
//输出每个字符的哈弗曼编码
tree.getBM(tree.root,"");
System.out.println("整个字符串的哈弗曼编码为:");
//数组遍历编码
for(int i=0;i<s.length();i++){
System.out.print(tree.SaveCode[s.charAt(i)]);
}
System.out.println();
//转换为byte类型
byte[] b=tree.ChangeCode();
System.out.println("转换为byte型后:");
for(int i=0;i<b.length;i++){
System.out.print(b[i]+" ");
}
}
}
如有不足欢迎指正!