哈夫曼编码译码java实现
针对只含有数字,字母的字符串,若有其他字符改动一下即可。
一下代码由本人手写,先写了c++再写的java(不怎么熟练java)有错欢迎交流。本人使用工具idea, jdk版本为11
转载请注明出处。
Main.class
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main {
//自定义比较类
// static Comparable<queueNode> nodeCmp = new Comparator<queueNode>() {
//
// public int compareTo(queueNode o1, queueNode o2) {
// //升序排序
// return o1.weight - o2.weight;
// }
// };
//创建哈夫曼树
public static void createHuffManTree(huffManNode[] huffManTree, char[] chars, int n, int[] cnt)
{
//小根堆
PriorityQueue<queueNode> heap = new PriorityQueue<queueNode>(520, new Comparator<queueNode>() {
@Override
public int compare(queueNode o1, queueNode o2) {
return o1.weight-o2.weight;
}
}
);
//入队
for(int i=1; i<=n; ++i) {
heap.add(new queueNode(cnt[chars[i]-'0'],i));
}
int m=n*2-1;
//初始化哈夫曼树数组
for(int i=1; i<=m; ++i){
if(i<=n) huffManTree[i]= new huffManNode(cnt[chars[i]-'0'],0,0,0);
else huffManTree[i]= new huffManNode(0,0,0,0);
}
//建树
for(int i= n+1; i<= m; ++i){
//找到最小的结点
queueNode minNode = heap.poll();
queueNode secondMinNode = heap.poll();
huffManTree[minNode.index].parent = i;
huffManTree[secondMinNode.index].parent = i;
huffManTree[i].leftChild = minNode.index;
huffManTree[i].rightChild = secondMinNode.index;
huffManTree[i].weight = minNode.weight + secondMinNode.weight;
//新结点加入小根堆
heap.add(new queueNode(huffManTree[i].weight,i));
}
}
public static void huffManEnCode(huffManCode[] huffManCodes, huffManNode[] huffManTree,char[] chars,int n) {
if(n==1) {
huffManCodes[1] = new huffManCode(chars[1],"0");
}
else {
//求n个叶子结点对应的哈夫曼编码
for(int i=1; i<=n; i++) {
// System.out.println("debughuffManEnCode");
String tmpCode ="";
int tmpIndex=2*n-1;
for(int j = i, p = huffManTree[i].parent; p!=0; j=p, p=huffManTree[p].parent){
if(huffManTree[p].leftChild==j) tmpCode+='0';
else tmpCode+='1';
}
char[] chars1 = tmpCode.toCharArray();
tmpCode="";
for(int j=chars1.length-1; j>=0; --j) {
tmpCode+=chars1[j];
}
huffManCodes[i]= new huffManCode(chars[i],tmpCode);
}
// System.out.println("debughuffManEnCode");
}
}
//获取输入url的 哈夫曼编码
public static String getHuffManCode(char[] urlchars,huffManCode[] huffManCodes,int n) {
String tmpCode="";
for(int i=0; i<urlchars.length; ++i) {
for(int j=1; j<=n; ++j) {
if(huffManCodes[j].ch==urlchars[i]) {
tmpCode+=huffManCodes[j].code;
break;
}
}
}
return tmpCode;
}
//将哈夫曼编码译码
public static String huffManDeCode(String tmpCode, huffManCode[] huffManCodes,huffManNode[] huffManTree,int n){
String myDecode="";
if(n==1) {
for(int i=0; i<tmpCode.length(); ++i) myDecode+=huffManCodes[1].code;
}
else{
int tmpIndex=2*n-1;
char[] tmpCodeChars = tmpCode.toCharArray();
for(int i=0; i<tmpCodeChars.length; ++i){
if(tmpCodeChars[i]=='0') tmpIndex=huffManTree[tmpIndex].leftChild;
else tmpIndex=huffManTree[tmpIndex].rightChild;
if(huffManTree[tmpIndex].leftChild ==0 &&huffManTree[tmpIndex].rightChild==0){
myDecode+=huffManCodes[tmpIndex].ch;
tmpIndex=2*n - 1;
}
}
}
return myDecode;
}
public static void main(String[] args) {
//创建对象
Scanner in = new Scanner(System.in);
//读入字符串用next(), 以空格划分
System.out.println("请输入url: ");
String url = in.next();
//将url转为char 数组
char[] urlChars = url.toCharArray();
//标记数组,判断哪些字符出现过
boolean[] visited = new boolean[520];
//取出url中的字符(去重后)
char[] chars = new char[urlChars.length+5];
//记录字符出现频次
int [] cnt = new int[200];
int len=0;
for(int i=0; i<urlChars.length; ++i) {
if(visited[urlChars[i]-'0']==false) {
chars[++len]=urlChars[i];
visited[urlChars[i]-'0']=true;
}
cnt[urlChars[i]-'0']++;
}
chars[len+1]='\0';
System.out.println(len);
//第一步: 建立一颗哈夫曼树
//定义一颗哈夫曼树数组
huffManNode[] huffManTree= new huffManNode[520];
createHuffManTree(huffManTree, chars,len, cnt);
//第二步: 进行哈夫曼编码
huffManCode[] huffManCodes = new huffManCode[520];
huffManEnCode(huffManCodes,huffManTree,chars,len);
//第三步:获取输入url的哈夫曼编码
String myHuffManEnCode = getHuffManCode(urlChars, huffManCodes,len);
String myHuffManDeCode = huffManDeCode(myHuffManEnCode, huffManCodes, huffManTree, len);
System.out.println("哈夫曼编码:"+myHuffManEnCode);
System.out.println("哈夫曼译码:"+myHuffManDeCode);
}
}
queueNode.class
//优先队列中的结点类型
public class queueNode {
public Integer weight;
public Integer index;
public queueNode(Integer weight, Integer index) {
this.weight = weight;
this.index = index;
}
}
huffManNode.class
//此类是哈夫曼树的结点,对应c++里面的一个结构体
public class huffManNode {
//public int parent;
//权重
public Integer weight;
//父亲结点
public Integer parent;
//左儿子结点
public Integer leftChild;
//右儿子结点
public Integer rightChild;
public huffManNode(Integer weight, Integer parent, Integer leftChild, Integer rightChild) {
this.weight = weight;
this.parent = parent;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
}
huffManCode.class
//此类存储每个字符对应的编码
public class huffManCode {
//ch代表对应的字符
public char ch;
//code代表ch对应字符的编码
public String code;
public huffManCode(char ch, String code) {
this.ch = ch;
this.code = code;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话