【Java】构建哈夫曼树和输出哈夫曼编码
2023-12-13 07:19:08
问题背景
一个单位有12个部门,每个部门都有一部电话,但是整个单位只有一根外线,当有电话打过来的时候,由转接员转到内线电话,已知各部门使用外线电话的频率为(次/天):5 20 10 12 8 43 5 6 9 15 19 32。
利用哈夫曼树算法思想设计内线电话号码,使得接线员拨号次数尽可能少。要求:
(1)依据使用外线电话的频率构造二叉树;
(2)输出设计出的各部门内线电话号码。
思路描述
- 构建哈夫曼树:将所有节点按权重值从小到大排序,从中取出最小的两个节点node1、node2,然后创建一个新的节点,新节点的左右子节点分别是node1、node2(左节点node1的权重值一定要比右节点node2小),新节点的权重值是node1和node2权重值之和,然后将新节点代替node1和node2加入节点队列中,重复该过程,直到节点队列中只剩下一个节点。
- 输入哈夫曼编码:在前面的构建好的二叉树中,左分支上标记0,右分支上标注1,从根节点到叶子节点所走过的路径就是该叶子节点的哈夫曼编码
?代码实现
/**
* 用二叉链表存储二叉树
*/
public class HTNode implements Comparable<HTNode>{
int weight;//权重
HTNode left,right;//左右子节点
public HTNode(int weight) {
this.weight = weight;
}
@Override
public int compareTo(HTNode o) {
return this.weight-o.weight;//从小到大排序
}
@Override
public String toString() {
return super.toString();
}
}
public class HuffmanTree {
//构建哈夫曼树
public static HTNode CreatHuffmanTree(int[] arr){
//初始化
if(arr.length<1)
return null;
List<HTNode> nodes=new ArrayList<>();
for(int weight:arr){
nodes.add(new HTNode(weight));
}
Collections.sort(nodes);//HTNodes实现了Comparable接口,基于weight排序
while (nodes.size()>1){//nodes中只剩下一个时,该节点就是根节点
//取权值最小的两个结点
HTNode htNode1 = nodes.get(0);
HTNode htNode2 = nodes.get(1);
HTNode parent=new HTNode(htNode1.weight+htNode2.weight);
parent.left=htNode1;
parent.right=htNode2;
nodes.remove(0);
nodes.remove(0);
nodes.add(parent);
Collections.sort(nodes);
}
return nodes.get(0);
}
public static void creatHuffmanCode(HTNode root,String append,StringBuilder code){
StringBuilder stringBuilder = new StringBuilder(code);
stringBuilder.append(append);
if(root.left==null&&root.right==null){
System.out.println("权值为"+root.weight+"的节点的哈夫曼编码为"+stringBuilder);
return;
}
creatHuffmanCode(root.left,"0",stringBuilder);
creatHuffmanCode(root.right,"1",stringBuilder);
}
//写个前序遍历验证一下构建的哈夫曼树是否正确
public static void preOrder(HTNode node){
if(node==null)
return;
System.out.print(node.weight+" ");
preOrder(node.left);
preOrder(node.right);
}
}
?运行结果
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入节点个数:");
int n=sc.nextInt();
int[] arr = new int[n];
System.out.println("请输入"+n+"个节点的权值:");
for(int i=0;i<n;i++){
arr[i]=sc.nextInt();
}
HTNode htNode = HuffmanTree.CreatHuffmanTree(arr);
System.out.println("前序遍历该哈夫曼树:");
HuffmanTree.preOrder(htNode);
System.out.println();
HuffmanTree.creatHuffmanCode(htNode,"",new StringBuilder());
}
}
?
?另外
- 为什么哈夫曼编码能够保证是前缀编码?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 要编码的字符都在叶子结点上,根结点到每一个叶子结点的路径一定是不同的
- ?为什么哈夫曼编码能够保证字符编码总长最短?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?哈夫曼树的带权路径长度是最小的,权重越大出现频率越高的字符越接近根结点
文章来源:https://blog.csdn.net/m0_73520938/article/details/134897799
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!