实现Huffman树

为了使得WPL即带权的外部结点路径最小,基本原则是:让权值大的结点离根近一些,权值小的结点离根远一些。实现方法:每次从未加入到树中的结点中选择两个权值最小的,即去权值最小和次小的结点作为左右子结点产生父结点,父结点的权值为这两个结点的权值之和,然后将父结点取代这两个结点带回去,继续循环。用数组作为存储结构。假定给定的外部结点权值数组中有m个元素,即有m个外部结点,那么内部结点就应该有m - 1个,创建一个容量为2 * m - 1的数组存放所有的结点,先用外部结点的权值初始化数组的前m个元素,然后循环填充后面的m - 1个元素,每次都是从第i个位置的前面查找没有加入树的最小和次小结点,形成一个新的结点,作为它们的父结点作为第m + i个结点元素。最后,设置根结点便可以得到这棵Huffman树。

直接上代码:

import java.util.LinkedList;
import java.util.Queue;


class HuffmanNode { //哈弗曼树中结点的数据结构
int w; //保存每个结点的权值

HuffmanNode left;
HuffmanNode right;
HuffmanNode parent;

public HuffmanNode(int w) {
this.w = w;
this.left = null;
this.right = null;
this.parent = null;
}
}


class HuffmanTree {
HuffmanNode root;
int n;

public HuffmanTree(int wA[]) {
int m = wA.length;
this.n = 2 * m - 1;
HuffmanNode hnA[] = new HuffmanNode[n];

for(int i = 0; i < m; i++) {
hnA[i] = new HuffmanNode(wA[i]); //初始化前m个结点
}

int min, scMin, i_min, i_scMin; //用来保存权值最小和次小的结点的权值和下标
for(int i = 0; i < m - 1; i++) {
min = scMin = Integer.MAX_VALUE; i_min = i_scMin = 0;
for(int j = 0; j < m + i; j++) { //每次从数组中第一个元素开始当前位置的前一个元素中进行查找
if(hnA[j].parent == null) {//这里的hnA[j].parent == null代表在未加入到树中的结点中查找

/*

*这里用到了一个时间复杂度为o(n)的查找最小元素和次小元素的技巧:如果当前元素比当前最小值小,那么更新次小值为当前最小值,最小值为当前值,否 *则,再与当前次小值进行比较,如果比次小值小,则更新次小值为当前元素。

*/
if(hnA[j].w < min) {
scMin = min;
i_scMin = i_min;
min = hnA[j].w;
i_min = j;
}
else {
if(hnA[j].w < scMin) {
scMin = hnA[j].w;
i_scMin = j;
}
}
}
}
hnA[m + i] = new HuffmanNode(min + scMin);
hnA[m + i].left = hnA[i_min];
hnA[m + i].right = hnA[i_scMin];
hnA[i_min].parent = hnA[i_scMin].parent = hnA[m + i];
}

root = hnA[n - 1];
}

public void print() {//这里实现了二叉树的层次换行打印,基本思想就是设置两个代表当前层和下一层结点数目的变量。
if(root == null)
return;
Queue<HuffmanNode> queue = new LinkedList<HuffmanNode>();

queue.offer(root);
HuffmanNode p;
int currNodes = 1, nextNodes = 0;
while(!queue.isEmpty()) {
p = queue.poll();
System.out.print(p.w + "\t");
currNodes--;

if(p.left != null) {
queue.offer(p.left);
nextNodes++;
}

if(p.right != null) {
queue.offer(p.right);
nextNodes++;
}

if(currNodes == 0) {//先统计下一层,再判断
System.out.println();
currNodes = nextNodes;
nextNodes = 0;
}
}
}
}


public class TestHuffmanTree {


public static void main(String[] args) {
int wA[] = {2,3,5,7,11,13,17,19,23,29,31,37,41};
HuffmanTree ht = new HuffmanTree(wA);
ht.print();
}


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值