昨天已经把基本准备工作做完了,今天主要是建立哈夫曼树。
- 第一步:创建叶子节点,将字符与对应的权值赋值给叶子节点
- 第二步:通过两个for循环建立哈夫曼树。外层循环 i 代表非叶子节点,内层循环 j 依次遍历当前已经存在的节点,两个内层循环可以选出其中权值最小的两个节点(这里需要一个标记数组,为了避免重复选择同一个),将两个权值最小的节点相加得到其父节点,最后连接其父子关系。具体过程如下图:
/**
*********************
* Construct the tree.
*
* @return HuffmanNode
* The Root
*********************
*/
public HuffmanNode constructTree() {
// Step 1. Allocate space.
nodes = new HuffmanNode[alphabetLength * 2 - 1];
boolean[] tempProcessed = new boolean[alphabetLength * 2 - 1];
// Step 2. Initialize leaves.
for (int i = 0; i < alphabetLength; ++i) {
nodes[i] = new HuffmanNode(alphabet[i], charCounts[i], null, null, null);
}//of for i
// Step 3. Construct the tree.
int templeft, tempright, tempMiniMal;
for (int i = alphabetLength; i < alphabetLength * 2 - 1; ++i) {
// Step 3.1 Select the first minimal as the left child.
templeft = -1;
tempMiniMal = Integer.MAX_VALUE;
for (int j = 0; j < i; ++j) {
if (tempProcessed[j]) {
continue;
}//of if
if (charCounts[j] < tempMiniMal) {
tempMiniMal = charCounts[j];
templeft = j;
}// Of if
}// Of for j
tempProcessed[templeft] = true;
// Step 3.2 Select the second minimal as the right child.
tempright = -1;
tempMiniMal = Integer.MAX_VALUE;
for (int j = 0; j < i; j++) {
if (tempProcessed[j]) {
continue;
}// Of if
if (charCounts[j] < tempMiniMal) {
tempMiniMal = charCounts[j];
tempright = j;
}// Of if
}// Of for j
tempProcessed[tempright] = true;
System.out.println("select " + templeft + " " + "and " + tempright);
// Step 3.3 Construct the new node.
charCounts[i] = charCounts[templeft] + charCounts[tempright];
nodes[i] = new HuffmanNode('*', charCounts[i], nodes[templeft], nodes[tempright], null);
// Step 3.4 Link with children.
nodes[templeft].parent = nodes[i];
nodes[tempright].parent = nodes[i];
System.out.println("The children of " + i + " are " + templeft + " and " + tempright);
}// Of for i
return nodes[nodes.length - 1];
}// Of constructTree
/**
* ********************
* Pre-order visit.
* ********************
*/
public void preOrderVisit(HuffmanNode paraNode) {
System.out.print("(" + paraNode.character + ", " + paraNode.weight + ") ");
if (paraNode.leftChild != null) {
preOrderVisit(paraNode.leftChild);
}// Of if
if (paraNode.rightChild != null) {
preOrderVisit(paraNode.rightChild);
}// Of if
return;
}// Of preOrderVisit
public static void main(String[] args) {
MyHuffman tempHuffman = new MyHuffman("C:/Users/胡来的魔术师/Desktop/test.txt");
tempHuffman.constructAlphabet();
HuffmanNode tempNode = tempHuffman.constructTree();
tempHuffman.preOrderVisit(tempNode);
}//of main
}//of MyHuffman
用先序遍历来试一下:
总结:确实今天开始写算法后,昨天还感觉很多的变量今天都能记住了,突然发现也没有想象中那么难,只要理清逻辑,一直就按部就班。