import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
/** 霍夫曼编码
* table = new int[][] { { 0, 0, 0, 0, 0, 0, 0 },
{ 'a', 7, 0, 0, 0, 0, 0 },
{ 'b', 0, 5, 0, 0, 0, 0 },
{ 'c', 0, 0, 3, 0, 0, 0 },
{ 'd', 0, 0, 0, 2, 0, 0 },
{ 'e', 0, 0, 0, 0, 12, 0 },
{ 'f', 0, 0, 0, 0, 0, 9 } };
二维数组里面第一列存放字符,字符对应行上放的是字符的频率或者出现次数
* */
public class Task8_31 {
private int[][] table;
private ArrayList<Point> Ppoints;//一个点的序列,Point类在下面,实际上一个点就是一个二叉树
private ArrayList<Point> huffmanTree;//我这里的 霍夫曼树 其实是个 “对象数组”,有五个元素,每个元素都保存着
//构造 真正“霍夫曼树”的五个中间节点
private String left = "1";
/** 构造函数 */
public Task8_31() {
Ppoints = new ArrayList<Point>();
huffmanTree = new ArrayList<Point>();
huffman();
Point point = huffmanTree.get(huffmanTree.size() - 1);
System.out.println("各个字符的霍夫曼编码为:");
huffamnCode(point);
}
/** 霍夫曼编码--使用递归,遍历霍夫曼树 */
public void huffamnCode(Point point) {// 霍夫曼编码,树的遍历 使用递归遍历
if (point.getLeftPoint() != null) {//算法设计很难,想了很久,断点debug了很久
System.out.print(left + " "
+ (char) Integer.parseInt(point.getLeftPoint().getName())
+ "/n");
left = "0" + left;
}
if (point.getRightPoint() != null) {
huffamnCode(point.getRightPoint());
}
// if(point.getLeftPoint() == null ){//左子树空不空无所谓
// System.out.print(left+"0"+(char)Integer.parseInt(point.getName())+"/n");
// System.out.print(left+"1"+(char)Integer.parseInt(tempPoint.getRightPoint().getName())+"/n");
// }
if (point.getRightPoint() == null) {// 关键是右子树对空进行判断
System.out.print(left.substring(0, left.length() - 1) + " "
+ (char) Integer.parseInt(point.getName()) + "/n");
}
}
/** 建造霍夫曼树 */
public void huffman() {// 霍夫曼树已经建造出来了,可是霍夫曼编码怎么输出?--思考中。。。
createTable();
createPpoints();
printPointsInfo();
Point[] points = findTheLowestTwoPoints();
huffmanTree.add(new Point("1", points[0], points[0].getWeight()
+ points[1].getWeight(), points[1]));
Ppoints.remove(0);
Ppoints.remove(0);
int timer = Ppoints.size();
int ref = 0;
while (timer > 0) {
Point point = Ppoints.get(0);
huffmanTree.add(new Point("1", point, point.getWeight()
+ huffmanTree.get(ref).getWeight(), huffmanTree.get(ref)));
timer--;
ref++;
Ppoints.remove(0);
}
}
public void printPointsInfo(){
Iterator<Point> it = Ppoints.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
/** 建表 */
public void createTable() {
table = new int[][] { { 0, 0, 0, 0, 0, 0, 0 },
{ 'a', 7, 0, 0, 0, 0, 0 }, { 'b', 0, 5, 0, 0, 0, 0 },
{ 'c', 0, 0, 3, 0, 0, 0 }, { 'd', 0, 0, 0, 2, 0, 0 },
{ 'e', 0, 0, 0, 0, 12, 0 }, { 'f', 0, 0, 0, 0, 0, 9 } };
}
/** 二叉树的构造,二叉树抽象为两颗子树为null的点 */
public void createPpoints() {
for (int i = 1; i < table.length; i++)
if (table[i][i] > 0) {
Ppoints.add(new Point(table[i][0] + "", null, table[i][i], null));
}
}
/** 返回点中权值最小的两个二叉树 */
@SuppressWarnings("unchecked")
public Point[] findTheLowestTwoPoints() {
Collections.sort(Ppoints);
return new Point[] { Ppoints.get(0), Ppoints.get(1) };
}
/** 主函数 */
public static void main(String[] args) {
new Task8_31();
}
}
/** 二叉树类 */
@SuppressWarnings("rawtypes")
class Point implements Comparable {// 实现Comparable接口,以便于排序
private String name = "";// 保存字符名称
private int weight = 0;// 保存权值
private Point leftPoint = null;// 左孩子
private Point rightPoint = null;// 右孩子
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public Point getLeftPoint() {
return leftPoint;
}
public void setLeftPoint(Point leftPoint) {
this.leftPoint = leftPoint;
}
public Point getRightPoint() {
return rightPoint;
}
public void setRightEdge1(Point rightPoint) {
this.rightPoint = rightPoint;
}
public Point() {
}
/** 构造*/
public Point(String name, Point leftPoint, int weight, Point rightPoint) {
this.weight = weight;
this.leftPoint = leftPoint;
this.rightPoint = rightPoint;
this.name = name;
}
@Override
public int compareTo(Object o) {
if (((Point) o).weight > this.weight)
return -1;
else if (((Point) o).weight == this.weight)
return 0;
else
return 1;
}
public String toString() {
return "点:" + (char) Integer.parseInt(name) + " " + leftPoint + " "
+ weight + " " + rightPoint;
}
}