先构建一个结点类,其结构中包含有权值、双亲值、左孩子、右孩子、角标和Huffman编码。将数组里的数据,利用顺序表实现存储,调用Collections集合存放数据,调用其sort方法实现排序。然后选取其中最小的两个子树进行建立Huffman树。逆序计算Huffman编码,一次球1~n个结点对应的编码。建立一个临时存储Huffman编码的字符的数组,从的一个结点开始,通过该结点找到其双亲,若该结点是双亲的左孩子,则向数组输入为“0”,若是右孩子,则输入“1”。将临时数组中的值逆序输入到所求结点对应的二维数组中的那一行。这样就得到了所有结点的Huffman编码。
源码如下
public class Haff {
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("请输入权值:");
int[] wightness = new int[number];
for (int i = 0; i < wightness.length; ++i) {
wightness[i] = scanner.nextInt();
}
for (int i = 0; i < number; ++i) {
Node node = new Node(wightness[i], i);
list.add(node);
}
Collections.sort(list);
huffmanTree();
}
private static ArrayList<Integer> selectTwoMin() {
ArrayList<Integer> List = 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;
}
}
}
List.add(first);
List.add(second);
return List;
}
public static void huffmanTree() {
for (int i = number; i < 2 * number - 1; i++) {
ArrayList<Integer> min = selectTwoMin();
Integer first = min.get(0);
Integer second = min.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);
}
for (Node node : list) {
node.huffmanCode(list);
node.show();
}
}
}
public class Node implements Comparable<Node> {
public int parent;
private int lchild;
private int rchild;
public double weight;
public int index;
public String code;
public Node(double weight, int index) {
super();
this.weight = weight;
this.index = index;
this.parent = -1; // 父节点初始化为-1,代表没有父节点
this.lchild = -1; // 左孩子初始化为-1,代表没有左孩子
this.rchild = -1; // 右结点初始化为-1,代表没有右孩子
this.code = "";
}
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.println("index wight rchild lchild code");
out.println(index+" "+weight+" "+rchild+" "+lchild+" "+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;
}
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();
}
}