哈夫曼树的定义与实现

**
*

  • 赫夫曼树的结点类

*/
public class HuffmanNode {
public int weight;// 结点的权值

public int flag;// 加入赫夫曼树的标志,flag=0时表示该结点未加入哈夫曼树,flag=1时则表示该结点已加入哈夫曼树

public HuffmanNode parent, lchild, rchild; // 父结点及左右孩子结点

public HuffmanNode() {// 构造一个空结点
	this(0);
}

public HuffmanNode(int weight) {// 构造一个具有权值的结点
	this.weight = weight;
	flag = 0;
	parent = lchild = rchild = null;
}

}

/**
*

  • 赫夫曼树及其操作

*/
public class HuffmanTree {

// 求赫夫曼编码的算法,W存放n个字符的权值(均>0)
public int[][] huffmanCoding(int[] W) {
	int n = W.length;// 字符个数
	int m = 2 * n - 1;// 赫夫曼树的结点数
	HuffmanNode[] HN = new HuffmanNode[m];
	int i;
	for (i = 0; i < n; i++)
		HN[i] = new HuffmanNode(W[i]);// 构造n个具有权值的结点

	for (i = n; i < m; i++) {// 建赫夫曼树
		// 在HN[0..i - 1]选择不在赫夫曼树中且weight最小的两个结点min1和min2
		HuffmanNode min1 = selectMin(HN, i - 1);
		min1.flag=1;
		HuffmanNode min2 = selectMin(HN, i - 1);
		min2.flag=1;

		// 构造min1和min2的父结点,并修改且父结点的权值
		HN[i] = new HuffmanNode();
		min1.parent=HN[i];
		min2.parent=HN[i];
		HN[i].lchild=min1;
		HN[i].rchild=min2;
		HN[i].weight=min1.weight + min2.weight;
	}

	// 从叶子到根逆向求每个字符的赫夫曼编码
	int[][] HuffCode = new int[n][n];// 分配n个字符编码存储空间
	for (int j = 0; j < n; j++) {
		int start = n - 1;// 编码的开始位置,初始化为数组的结尾
		for (HuffmanNode c = HN[j], p = c.parent; p != null; c = p, p = p.parent)
			// 从叶子到根逆向求编码
			if (p.lchild.equals(c))// 左孩子编码为0
				HuffCode[j][start--] = 0;
			else
				// 右孩子编码为1
				HuffCode[j][start--] = 1;
		HuffCode[j][start] = -1;// 编码的开始标志为 -1,编码是-1之后的0、1序列
	}
	return HuffCode;
}

// 在HN[0..i - 1]选择不在赫夫曼树中且weight最小的结点
private HuffmanNode selectMin(HuffmanNode[] HN, int end) {
	HuffmanNode min = HN[end];
	for (int i = 0; i <= end; i++) {
		HuffmanNode h = HN[i];
		if (h.flag == 0 && h.weight < min.weight)// 不在赫夫曼树中且weight最小的结点
			min = h;
	}
	return min;
}

public static void main(String[] args) {
	int[] W = { 23, 11, 5, 3, 29, 14, 7, 8 };// 初始化权值
	HuffmanTree T = new HuffmanTree();// 构造赫夫曼树
	int[][] HN = T.huffmanCoding(W);// 求赫夫曼编码

	System.out.println("赫夫曼编码为:");
	for (int i = 0; i < HN.length; i++) {// 输出赫夫曼编码
		System.out.print(W[i] + " ");
		for (int j = 0; j < HN[i].length; j++) {
			if (HN[i][j] == -1) {// 开始标志符读到数组结尾
				for (int k = j + 1; k < HN[i].length; k++)
					System.out.print(HN[i][k]);// 输出
				break;
			}
		}
		System.out.println();// 输出换行
	}
}

}

// 运行结果:
// 赫夫曼编码为:
// 23 01
// 11 001
// 5 11111
// 3 11110
// 29 10
// 14 110
// 7 1110
// 8 000

你可能感兴趣的:(java,数据结构)