我看大神们写的文章,每个人理解的角度都不一样,于是我决定自己写一写
跟别人的思路都不一样,我也不知道对不对
首先是结点类型的定义
package 哈弗曼树;
import static java.lang.System.out;
import java.util.List;
public class Node implements Comparable<Node> {
private String name;
public int parent;
private int lchild;
private int rchild;
public double weight;
public int index;
public String code;
public Node(String name, double weight, int index) {
super();
this.name = name;
this.weight = weight;
this.index = index;
this.parent = -1; // 父节点初始化为-1,代表没有父节点
this.lchild = -1; // 左孩子初始化为-1,代表没有左孩子
this.rchild = -1; // 右结点初始化为-1,代表没有右孩子
this.code = "";
}
/**
* Compares this object with the specified object for order.
* Returns a negative integer, zero, or a positive integer
* as this object is less than, equal to, or greater than the specified object
* */
@Override
public int compareTo(Node o) {
if(this.weight < o.weight)
return -1;
else if(this.weight > o.weight)
return 1;
return 0;
}
public void show() {
out.printf("name = %-2s lchild = %-2d rchild = %-2d "
+ "index = %-2d parent = %-2d weight = %.2f"
+ " code = %s\n",
name ,lchild ,rchild ,index ,parent ,weight,code);
}
public void setLchild(int lchild) {
this.lchild = lchild;
}
public void setRchild(int rchild) {
this.rchild = rchild;
}
public void setParent(int parent) {
this.parent = parent;
}
/**
* 实现求该结点的哈夫曼编码
* @param list 以下标形式表示的哈夫曼树
*/
public void huffmanCode(List<Node> list) {
int parent = this.parent;
int index = this.index;
while (parent != -1) { //结点的父节点为-1代表这个结点是根节点,树叶不断寻找父节点,由下向上求哈夫曼编码
if (list.get(parent).lchild == index)
code += "0"; //如果树叶是 树叶父节点 的左孩子
else
code += "1";
index = list.get(parent).index;
parent = list.get(parent).parent;
}
StringBuffer reverse = new StringBuffer(); //真正的哈夫曼编码是由根部到树叶,所以需要逆序
for (int i = code.length() - 1; i >= 0; --i)
reverse.append(code.charAt(i));
code = reverse.toString();
}
}
然后是在主函数实现
package 哈弗曼树;
import static java.lang.System.out;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
/*测试数据*/
/*a b c d
0.1 0.2 0.3 0.4
a b c d e f
45 13 12 16 9 5*/
public class HuffmanTree {
public static int number;
static List<Node> list;
public static void main(String[] args) {
list = new ArrayList<Node>();
out.println("请输入字符的个数");
Scanner scanner = new Scanner(System.in);
number = scanner.nextInt();
out.println("请输入" + number + "个字符");
String[] c = new String[number];
for (int i = 0; i < c.length; ++i)
c[i] = scanner.next();
out.println("请输入字符对应的频率");
double[] freq = new double[number];
for (int i = 0; i < freq.length; ++i)
freq[i] = scanner.nextDouble();
for (int i = 0; i < number; ++i) {
Node node = new Node(c[i], freq[i], i);
list.add(node);
}
Collections.sort(list);
huffmanTree();
scanner.close();
}
/**
* @return : 权重最大值和次大值所在下标
*/
private static ArrayList<Integer> selectTwoMin() {
ArrayList<Integer> two = new ArrayList<Integer>();
Integer first = 0, second = 0;/* 两个最小值都初始化为下表为0 */
double small1, small2;
small1 = small2 = Double.MAX_VALUE;/* 将最大值和最小值初始化为double类型的最大值 */
for (int i = 0; i < list.size(); ++i) {
if (list.get(i).parent == -1) {
if (small1 > list.get(i).weight) {
second = first;/* 更新次小的值 */
small2 = small1;
small1 = list.get(i).weight;/* 更新最小值 */
first = i;
} else if (small2 > list.get(i).weight) {
small2 = list.get(i).weight;/* 更新次小值 */
second = i;
}
}
}
two.add(first);
two.add(second);
return two;
}
/**
* 求哈夫曼树:通过selectTwoMin()找到两个最小结点在list中的下标first,second
* 形成新的结点node,权值为first.weight + first.weight 将first,second的父节点域更新为node的下标
* node.left = first , node.right = second
*/
public static void huffmanTree() {
for (int i = number; i < 2 * number - 1; ++i) {
ArrayList<Integer> two = selectTwoMin();
Integer first = two.get(0);
Integer second = two.get(1);
Node left = list.get(first);
Node right = list.get(second);
left.setParent(i);
right.setParent(i);
Node parent = new Node("*", left.weight + right.weight, i);
parent.setLchild(list.get(first).index);
parent.setRchild(list.get(second).index);
list.add(parent);
}
out.println("***************");
for (Node node : list) {
node.huffmanCode(list);
node.show();
}
}
}
也不知道对不对,我测试的数据是对的
而且没有进行异常处理,比如数据类型不匹配之类的
我总觉得那是算法之外的
考虑起来挺麻烦的吼吼吼~~~