Java数据结构——Java语言下实现赫夫曼编码

Huffman

  • 导入
import java.io.*;
import java.util.Scanner;
  • huffman类的描述
/**
 * 把想要翻译的英文文本,自己,写入text.txt文件中
 * 至少2个字符
 * 程序会自动计算每个字符的权值,构造赫夫曼树,生成每个字符的赫夫曼编码
 * @author 己千之
 */
  • 类的成员变量
	/**
	 * 叶子节点个数
	 */
	int n;
	
	/**
	 * 总节点个数
	 */
	int m;
	
	/**
	 * 每次权值最小的两个
	 */
	int s1, s2;
	
	/**
	 * text.txt文件里的内容
	 */
	String textString;
	
	/**
	 * code.txt文件里的内容
	 */
	String codeString;
  • 内部类:作节点
	/**
	 * 内部类
	 * 赫夫曼树的节点的数据结构
	 * @author 己千之
	 */
	class HuffmanTreeNode {
		char data;
		int weight;
		HuffmanTreeNode parent, lchild, rchild;
		
		HuffmanTreeNode() {
			data = '0';
			weight = 0;
			parent = lchild = rchild = null;
		}
		HuffmanTreeNode(char a, int b, HuffmanTreeNode c, HuffmanTreeNode d, HuffmanTreeNode e) {
			data = a;
			weight = b;
			parent = c;
			lchild = d;
			rchild = e;
		}
	}
	
	/**
	 * 赫夫曼编码的数据结构
	 * @author 己千之
	 */
	class HuffmanCodeNode {
		char data;
		String code;
		
		HuffmanCodeNode() {
			data = '0';
			code = "0";
		}
		HuffmanCodeNode(char a, String b) {
			data = a;
			code = b;
		}
		public String toString() {
			return "< "+data+" "+code+" >";
		}
	}
	
	/**
	 * 叶子节点的数据结构
	 * @author 己千之
	 */
	class LeafNode {
		char data;
		int weight;
		
		LeafNode() {
			data = '0';
			weight = 0;
		}
		LeafNode(char a, int b) {
			data = a;
			weight = b;
		}
		public String toString() {
			return "< "+data+" "+weight+" >";
		}
	}
  • 初始
	LeafNode[] w = new LeafNode[128];
	HuffmanTreeNode[] HTNode = new HuffmanTreeNode[255];
	HuffmanCodeNode[] HCNode = new HuffmanCodeNode[255];
  • 基本方法
	public void setN(int num) {
		n = num;
	}
	public void setM(int num) {
		m = num;
	}
	public void setS1(int num) {
		s1 = num;
	}
	public void setS2(int num) {
		s2 = num;
	}
  • 注意1:writeToText()
	/**
	 * 假如你不想输入,你可以在Main()方法中把writeToText(filename1)去掉
	 * 可以直接把你想翻译的文本输进text.txt文本就行
	 */
  • 注意2:Main()
	/**
	 * 对赫夫曼方法的集成
	 * 因为我试了,少了任何一个方法没有调用,程序就会报错。
	 */
  • 写入文件
	/**
	 * 假如你不想输,你可以在Main()方法中把writeToText(filename1)去掉
	 * 可以直接把你想翻译的文本输进text.txt文本就行
	 * @param filename
	 */
	public void writeToText(String filename) {
		System.out.println("请输入文本:");
		
		Scanner sc = new Scanner(System.in);
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(filename));
			out.write(sc.nextLine());
			
			out.close();
			sc.close();
			System.out.println("操作成功!");
		}catch(IOException e) {
			e.printStackTrace(); // 显示错误信息,和位置
		}
	}
  • 统计字符次数
	/**
	 * 读取text.txt文件内容
	 * 计算每个字符出现的次数
	 * @param filename
	 */
	public void readCount(String filename) {
		
		BufferedReader reader = null;
		StringBuffer strBuffer = null;
		
		try {
			reader = new BufferedReader(new FileReader(filename));
			strBuffer = new StringBuffer();
			
			String lines;
			while((lines=reader.readLine()) != null) {
				strBuffer.append(lines);
			}
		} catch (IOException e) {
			// 以StringBuffer为操作
			e.printStackTrace();
		} finally {
			if(reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} // end try...
		
		String text = new String(strBuffer);
		System.out.println("一、读取文本为:");
		System.out.println(text);
		textString = text;
		
		// 去重
		String newText = "";
		for(int i=0; i<text.length(); i++) {
			// indexof():对大小写敏感,对没出现的字符返回-1
			if(newText.indexOf(text.charAt(i)) == -1) {
				
				newText += text.charAt(i);
			}
		}
		
		// 返回叶子个数
		setN(newText.length());
		setM(2*n-1);
		
		// 统计字符次数
		System.out.println("二、统计结果为 ( < 字符  权值 > ) :");
		for(int i=0; i<newText.length(); i++) {
			
			int count = 0;
			for(int j=0; j<text.length(); j++) {
				
				if(newText.charAt(i) == text.charAt(j)) {
					
					count++;
				}
			}

			LeafNode LNode = new LeafNode(newText.charAt(i), count);
			System.out.println(LNode.toString());
			
			w[i+1] = LNode;
		}
		
		System.out.println("(共"+n+"种字符)");

	} // end ReadCount
  • select
	/**
	 * 构造赫夫曼树用到的函数,选取权值最小的两个节点的位置
	 * @param HT
	 * @param n
	 */
	public void selectMin(HuffmanTreeNode[] HT, int n) {
		int i;
		for(i=1; i<=n; i++) {
			if(HT[i].parent == null) {
				setS1(i);
				break;
			}
		}
		for(i=1; i<=n; i++) {
			if(HT[i].parent==null && HT[s1].weight>HT[i].weight) {
				setS1(i);
			}
		}
		for(i=1; i<=n; i++) {
			if(HT[i].parent==null && i!=s1) {
				setS2(i);
				break;
			}
		}
		for(i=1; i<=n; i++) {
			if(HT[i].parent==null && HT[s2].weight>HT[i].weight && i!=s1) {
				setS2(i);
			}
		}
	} // end select
  • 构建赫夫曼树
	/**
	 * 构建赫夫曼树
	 */
	public void creatHuffmanTree() {
		int i;
		
		// init
		for(i=1; i<=n; i++) {
			HTNode[i] = new HuffmanTreeNode(w[i].data, w[i].weight, null, null, null);
		}
		for(i=n+1; i<=m; i++) {
			HTNode[i] = new HuffmanTreeNode();
		}
		
		// 建叶子以上的节点,链接
		for(i=n+1; i<=m; i++) {
			
			selectMin(HTNode, i-1);
			
			HTNode[s1].parent = HTNode[i]; HTNode[s2].parent = HTNode[i];
			HTNode[i].lchild = HTNode[s1]; HTNode[i].rchild = HTNode[s2];
			
			HTNode[i].weight = HTNode[s1].weight+HTNode[s2].weight;
		}
		
	} // end creatHuffmanTree
  • 写入code文件
	/**
	 * 把text转化成赫夫曼报文 存储到 code文件
	 * @param filename2
	 */
	public void writeCodeToFile(String filename2) {
		String tempString = "";
		
		for(int i=0; i<textString.length(); i++) {
			char ch = textString.charAt(i);
			for(int j=1; j<=n; j++) {
				
				if(ch == HCNode[j].data) {
					tempString += HCNode[j].code;
				}
			}
		}
		
		System.out.println("四、赫夫曼报文:");
		System.out.println(tempString);
		
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(filename2));
			out.write(tempString);
			out.close();
			System.out.println("五、把赫夫曼报文储存到code文件,操作成功!");
		}catch(IOException e) {
			e.printStackTrace(); // 显示错误信息,和位置
		}
		
		codeString = tempString;
	}
  • 编码
	/**
	 * 编码
	 */
	public void encoding() {
		int i;
		
		// encoding
		for(i=1; i<=n; i++) {
			// init
			HCNode[i] = new HuffmanCodeNode();
			
			// data
			HCNode[i].data = HTNode[i].data;
			
			// code
			HuffmanTreeNode tempNode;
			tempNode = HTNode[i];
			String tempString = "";
			
			while(tempNode.parent != null) {
				if(tempNode == tempNode.parent.lchild) tempString = "0" + tempString;
				else tempString = "1" + tempString;
				
				tempNode = tempNode.parent;
			}
			
			HCNode[i].code = tempString;
			
		}
		
		// 打印
		System.out.println("三、每个字符对应的编码为:( < 字符 赫夫曼编码 > )");
		for(i=1; i<=n; i++) {
			System.out.println(HCNode[i].toString());
		}

	} // end encoding
  • 译码
	/**
	 * 译码
	 */
	public void decoding() {
		int i;
		HuffmanTreeNode tempNode;
		String tempString = "";
		
		tempNode = HTNode[2*n-1];
		for(i=0; i<codeString.length(); i++) {
			if(codeString.charAt(i) == '0') {
				tempNode = tempNode.lchild;
			}
			else {
				tempNode = tempNode.rchild;
			}
			
			if(tempNode.lchild == null) {
				tempString += tempNode.data;
				tempNode = HTNode[2*n-1];
			}
		}
		
		System.out.println("六、根据code文件的码,译文:");
		System.out.println(tempString);
	} // end decoding
  • 方法集成
	/**
	 * 对赫夫曼方法的集成
	 * 因为我试了,少了任何一个方法没有调用,程序就会报错。
	 * @param filename1
	 * @param filename2
	 */
	public void Main(String filename1, String filename2) {
		writeToText(filename1);
		readCount(filename1);
		creatHuffmanTree();
		encoding();
		writeCodeToFile(filename2);
		decoding();
	}
  • 测试类
public class Test_Huffman {

	public static void main(String[] args) {
		final String filepath1 = "D:\\Java Space\\Java 0~100\\src\\Huffman\\text.txt";
		final String filepath2 = "D:\\Java Space\\Java 0~100\\src\\Huffman\\code.txt";
		
		Huffman huffman = new Huffman();
		
		huffman.Main(filepath1, filepath2);
	}

}
  • 效果图

在这里插入图片描述

  • 源码:

拷贝即用,只需要在D盘下面新建:
text.txt和code.txt

import java.io.*;
import java.util.Scanner;

/**
 * 把想要翻译的英文文本,自己,写入text.txt文件中
 * 至少2个字符
 * 程序会自动计算每个字符的权值,构造赫夫曼树,生成每个字符的赫夫曼编码
 * @author 己千之
 */
class Huffman {
	
	/**
	 * 叶子节点个数
	 */
	int n;
	
	/**
	 * 总节点个数
	 */
	int m;
	
	/**
	 * 每次权值最小的两个
	 */
	int s1, s2;
	
	/**
	 * text.txt文件里的内容
	 */
	String textString;
	
	/**
	 * code.txt文件里的内容
	 */
	String codeString;
	
	
	/**
	 * 内部类
	 * 赫夫曼树的节点的数据结构
	 * @author 己千之
	 */
	class HuffmanTreeNode {
		char data;
		int weight;
		HuffmanTreeNode parent, lchild, rchild;
		
		HuffmanTreeNode() {
			data = '0';
			weight = 0;
			parent = lchild = rchild = null;
		}
		HuffmanTreeNode(char a, int b, HuffmanTreeNode c, HuffmanTreeNode d, HuffmanTreeNode e) {
			data = a;
			weight = b;
			parent = c;
			lchild = d;
			rchild = e;
		}
	}
	
	/**
	 * 赫夫曼编码的数据结构
	 * @author 己千之
	 */
	class HuffmanCodeNode {
		char data;
		String code;
		
		HuffmanCodeNode() {
			data = '0';
			code = "0";
		}
		HuffmanCodeNode(char a, String b) {
			data = a;
			code = b;
		}
		public String toString() {
			return "< "+data+" "+code+" >";
		}
	}
	
	/**
	 * 叶子节点的数据结构
	 * @author 己千之
	 */
	class LeafNode {
		char data;
		int weight;
		
		LeafNode() {
			data = '0';
			weight = 0;
		}
		LeafNode(char a, int b) {
			data = a;
			weight = b;
		}
		public String toString() {
			return "< "+data+" "+weight+" >";
		}
	}
	
	LeafNode[] w = new LeafNode[128];
	HuffmanTreeNode[] HTNode = new HuffmanTreeNode[255];
	HuffmanCodeNode[] HCNode = new HuffmanCodeNode[255];
	
	public void setN(int num) {
		n = num;
	}
	public void setM(int num) {
		m = num;
	}
	public void setS1(int num) {
		s1 = num;
	}
	public void setS2(int num) {
		s2 = num;
	}
	
	/**
	 * 假如你不想输,你可以在Main()方法中把writeToText(filename1)去掉
	 * 可以直接把你想翻译的文本输进text.txt文本就行
	 * @param filename
	 */
	public void writeToText(String filename) {
		System.out.println("请输入文本:");
		
		Scanner sc = new Scanner(System.in);
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(filename));
			out.write(sc.nextLine());
			
			out.close();
			sc.close();
			System.out.println("操作成功!");
		}catch(IOException e) {
			e.printStackTrace(); // 显示错误信息,和位置
		}
	}
	
	/**
	 * 读取text.txt文件内容
	 * 计算每个字符出现的次数
	 * @param filename
	 */
	public void readCount(String filename) {
		
		BufferedReader reader = null;
		StringBuffer strBuffer = null;
		
		try {
			reader = new BufferedReader(new FileReader(filename));
			strBuffer = new StringBuffer();
			
			String lines;
			while((lines=reader.readLine()) != null) {
				strBuffer.append(lines);
			}
		} catch (IOException e) {
			// 以StringBuffer为操作
			e.printStackTrace();
		} finally {
			if(reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} // end try...
		
		String text = new String(strBuffer);
		System.out.println("一、读取文本为:");
		System.out.println(text);
		textString = text;
		
		// 去重
		String newText = "";
		for(int i=0; i<text.length(); i++) {
			// indexof():对大小写敏感,对没出现的字符返回-1
			if(newText.indexOf(text.charAt(i)) == -1) {
				
				newText += text.charAt(i);
			}
		}
		
		// 返回叶子个数
		setN(newText.length());
		setM(2*n-1);
		
		// 统计字符次数
		System.out.println("二、统计结果为 ( < 字符  权值 > ) :");
		for(int i=0; i<newText.length(); i++) {
			
			int count = 0;
			for(int j=0; j<text.length(); j++) {
				
				if(newText.charAt(i) == text.charAt(j)) {
					
					count++;
				}
			}

			LeafNode LNode = new LeafNode(newText.charAt(i), count);
			System.out.println(LNode.toString());
			
			w[i+1] = LNode;
		}
		
		System.out.println("(共"+n+"种字符)");

	} // end ReadCount
	
	/**
	 * 构造赫夫曼树用到的函数,选取权值最小的两个节点的位置
	 * @param HT
	 * @param n
	 */
	public void selectMin(HuffmanTreeNode[] HT, int n) {
		int i;
		for(i=1; i<=n; i++) {
			if(HT[i].parent == null) {
				setS1(i);
				break;
			}
		}
		for(i=1; i<=n; i++) {
			if(HT[i].parent==null && HT[s1].weight>HT[i].weight) {
				setS1(i);
			}
		}
		for(i=1; i<=n; i++) {
			if(HT[i].parent==null && i!=s1) {
				setS2(i);
				break;
			}
		}
		for(i=1; i<=n; i++) {
			if(HT[i].parent==null && HT[s2].weight>HT[i].weight && i!=s1) {
				setS2(i);
			}
		}
	} // end select
	
	/**
	 * 构建赫夫曼树
	 */
	public void creatHuffmanTree() {
		int i;
		
		// init
		for(i=1; i<=n; i++) {
			HTNode[i] = new HuffmanTreeNode(w[i].data, w[i].weight, null, null, null);
		}
		for(i=n+1; i<=m; i++) {
			HTNode[i] = new HuffmanTreeNode();
		}
		
		// 建叶子以上的节点,链接
		for(i=n+1; i<=m; i++) {
			
			selectMin(HTNode, i-1);
			
			HTNode[s1].parent = HTNode[i]; HTNode[s2].parent = HTNode[i];
			HTNode[i].lchild = HTNode[s1]; HTNode[i].rchild = HTNode[s2];
			
			HTNode[i].weight = HTNode[s1].weight+HTNode[s2].weight;
		}
		
	} // end creatHuffmanTree
	
	/**
	 * 把text转化成赫夫曼报文 存储到 code文件
	 * @param filename2
	 */
	public void writeCodeToFile(String filename2) {
		String tempString = "";
		
		for(int i=0; i<textString.length(); i++) {
			char ch = textString.charAt(i);
			for(int j=1; j<=n; j++) {
				
				if(ch == HCNode[j].data) {
					tempString += HCNode[j].code;
				}
			}
		}
		
		System.out.println("四、赫夫曼报文:");
		System.out.println(tempString);
		
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(filename2));
			out.write(tempString);
			out.close();
			System.out.println("五、把赫夫曼报文储存到code文件,操作成功!");
		}catch(IOException e) {
			e.printStackTrace(); // 显示错误信息,和位置
		}
		
		codeString = tempString;
	}
	
	/**
	 * 编码
	 */
	public void encoding() {
		int i;
		
		// encoding
		for(i=1; i<=n; i++) {
			// init
			HCNode[i] = new HuffmanCodeNode();
			
			// data
			HCNode[i].data = HTNode[i].data;
			
			// code
			HuffmanTreeNode tempNode;
			tempNode = HTNode[i];
			String tempString = "";
			
			while(tempNode.parent != null) {
				if(tempNode == tempNode.parent.lchild) tempString = "0" + tempString;
				else tempString = "1" + tempString;
				
				tempNode = tempNode.parent;
			}
			
			HCNode[i].code = tempString;
			
		}
		
		// 打印
		System.out.println("三、每个字符对应的编码为:( < 字符 赫夫曼编码 > )");
		for(i=1; i<=n; i++) {
			System.out.println(HCNode[i].toString());
		}

	} // end encoding
	
	/**
	 * 译码
	 */
	public void decoding() {
		int i;
		HuffmanTreeNode tempNode;
		String tempString = "";
		
		tempNode = HTNode[2*n-1];
		for(i=0; i<codeString.length(); i++) {
			if(codeString.charAt(i) == '0') {
				tempNode = tempNode.lchild;
			}
			else {
				tempNode = tempNode.rchild;
			}
			
			if(tempNode.lchild == null) {
				tempString += tempNode.data;
				tempNode = HTNode[2*n-1];
			}
		}
		
		System.out.println("六、根据code文件的码,译文:");
		System.out.println(tempString);
	} // end decoding
	
	/**
	 * 对赫夫曼方法的集成
	 * 因为我试了,少了任何一个方法没有调用,程序就会报错。
	 * @param filename1
	 * @param filename2
	 */
	public void Main(String filename1, String filename2) {
		writeToText(filename1);
		readCount(filename1);
		creatHuffmanTree();
		encoding();
		writeCodeToFile(filename2);
		decoding();
	}
	
} // end huffman
public class Main {

	public static void main(String[] args) {
		final String filepath1 = "D:\\text.txt";
		final String filepath2 = "D:\\code.txt";
		
		Huffman huffman = new Huffman();
		
		huffman.Main(filepath1, filepath2);
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姜满月

鼓励,鼓励,更加努力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值