Day 21: 二叉树的深度遍历的递归实现
在递归实现求深度和结点数量部分,关键是要列出所有情况,比如:无叶子结点,只有左孩子、只有右孩子,左右孩子都有的情况。
21.1 代码
package datastructure;
import java.util.Arrays;
/**
* Binary tree with char type elements.
*
* @author XuQiong
*
*/
public class BinaryCharTree {
/**
* The value in char.
*/
char value;
/**
* The left child.
*/
BinaryCharTree leftChild;
/**
* The right child.
*/
BinaryCharTree rightChild;
/**
* ***********************
* The first constructor.
*
* @param paraName
* The value.
* ***********************
*/
public BinaryCharTree(char paraName) {
value = paraName;
leftChild = null;
rightChild = null;
}
/**
* **********************
* Manually construct a tree. Only for testing.
* **********************
*/
public static BinaryCharTree manualConstructTree() {
// Step 1. Construct a tree with only one node.
BinaryCharTree resultTree = new BinaryCharTree('a');
//Step 2. Construct all nodes. The first node is root.
//BinaryCharTreeNode tempTreeA = resultTree.root;
BinaryCharTree tempTreeB = new BinaryCharTree('b');
BinaryCharTree tempTreeC = new BinaryCharTree('c');
BinaryCharTree tempTreeD = new BinaryCharTree('d');
BinaryCharTree tempTreeE = new BinaryCharTree('e');
BinaryCharTree tempTreeF = new BinaryCharTree('f');
BinaryCharTree tempTreeG = new BinaryCharTree('g');
//Step 3. Link all nodes.
resultTree.leftChild = tempTreeB;
resultTree.rightChild = tempTreeC;
tempTreeB.rightChild = tempTreeD;
tempTreeC.leftChild = tempTreeE;
tempTreeD.leftChild = tempTreeF;
tempTreeD.rightChild = tempTreeG;
return resultTree;
}// Of manualConstructTree
/**
* ***********************************
* Pre-order visit.
* ***********************************
*/
public void preOderVisit() {
System.out.println("" + value + "");
if(leftChild != null) {
leftChild.preOderVisit();
}// Of if
if(rightChild != null) {
rightChild.preOderVisit();
}// Of if
}// Of preOrderVisit
/**
* **********************************
* In-order visit.
* **********************************
*/
public void inOderVisit() {
if(leftChild != null) {
leftChild.preOderVisit();
}// Of if
System.out.println("" + value + "");
if(rightChild != null) {
rightChild.preOderVisit();
}// Of if
}// Of inOrderVisit
/**
* *********************************
* Post-order visit.
* *********************************
*/
public void postOrderVisit() {
if(leftChild != null) {
leftChild.preOderVisit();
}// Of if
if(rightChild != null) {
rightChild.preOderVisit();
}// Of if
System.out.println("" + value + "");
}// Of postOrderVisit
/**
* **********************************
* Get the depth of the binary tree.
*
* @return The depth. It is 1 if there is only one code, i.e., the root.
* **********************************
*/
public int getDepth() {
// It is a leaf.
if (leftChild == null && rightChild == null) {
return 1;
}// Of if
//Only rightChild.
if (leftChild == null) {
return rightChild.getDepth() + 1;
}
//Only leftChild.
if (rightChild == null) {
return leftChild.getDepth() + 1;
}
//Both rightChild and leftChild.
if(leftChild.getDepth() > rightChild.getDepth()) {
return leftChild.getDepth() + 1;
} else {
return rightChild.getDepth() + 1;
}// Of if
}// Of depth
/**
* ***********************************
* Get the number of the nodes.
*
* @return The number of nodes.
* ***********************************
*/
public int getNumNodes() {
// It is a leaf.
if(leftChild == null && rightChild == null) {
return 1;
}// Of if
//Only rightChild.
if (leftChild == null) {
return rightChild.getNumNodes() + 1;
}
//Only leftChild.
if (rightChild == null) {
return leftChild.getNumNodes() + 1;
}
//Both rightChild and leftChild.
return leftChild.getNumNodes() + rightChild.getNumNodes() + 1;
}
/**
* ************************************
* The entrance of the program.
*
* @param args
* Not used now.
* ************************************
*/
public static void main(String args[]) {
BinaryCharTree tempTree = manualConstructTree();
System.out.println("\r\nPreorder visit:");
tempTree.preOderVisit();
System.out.println("\r\nInorder visit:");
tempTree.inOderVisit();
System.out.println("\r\nPostorder visit:");
tempTree.postOrderVisit();
System.out.println("\r\n\r\nThe depth is:" + tempTree.getDepth());
System.out.println("\r\n\r\nThe number of nodes is:" + tempTree.getNumNodes());
}// Of main
}// Of BinaryCharTree
22.2 运行结果
Day 22:二叉树的存储
今天遇到一个bug,main 函数中少写了一个参数 String args[],程序无法识别为主函数,无法运行。
将二叉树结点与索引存储在两个向量中,需要利用队列,对二叉树进行广度优先遍历,保证访问的结点顺序是从上到下,从左到右。
22.1 代码实现
package datastructure;
import java.util.Arrays;
import datastructure.*;
/**
* Binary tree with char type elements.
*
* @author XuQiong
*
*/
public class BinaryCharTree {
/**
* The value in char.
*/
char value;
/**
* The left child.
*/
BinaryCharTree leftChild;
/**
* The right child.
*/
BinaryCharTree rightChild;
/**
* The value of nodes according to breadth first traversal.
*/
char[] valuesArray;
/**
* The indices in the complete binary tree.
*/
int[] indicesArray;
/**
* ***********************
* The first constructor.
*
* @param paraName
* The value.
* ***********************
*/
public BinaryCharTree(char paraName) {
value = paraName;
leftChild = null;
rightChild = null;
}
/**
* **********************
* Manually construct a tree. Only for testing.
* **********************
*/
public static BinaryCharTree manualConstructTree() {
// Step 1. Construct a tree with only one node.
BinaryCharTree resultTree = new BinaryCharTree('a');
//Step 2. Construct all nodes. The first node is root.
//BinaryCharTreeNode tempTreeA = resultTree.root;
BinaryCharTree tempTreeB = new BinaryCharTree('b');
BinaryCharTree tempTreeC = new BinaryCharTree('c');
BinaryCharTree tempTreeD = new BinaryCharTree('d');
BinaryCharTree tempTreeE = new BinaryCharTree('e');
BinaryCharTree tempTreeF = new BinaryCharTree('f');
BinaryCharTree tempTreeG = new BinaryCharTree('g');
//Step 3. Link all nodes.
resultTree.leftChild = tempTreeB;
resultTree.rightChild = tempTreeC;
tempTreeB.rightChild = tempTreeD;
tempTreeC.leftChild = tempTreeE;
tempTreeD.leftChild = tempTreeF;
tempTreeD.rightChild = tempTreeG;
return resultTree;
}// Of manualConstructTree
/**
* ***********************************
* Pre-order visit.
* ***********************************
*/
public void preOderVisit() {
System.out.println("" + value + "");
if(leftChild != null) {
leftChild.preOderVisit();
}// Of if
if(rightChild != null) {
rightChild.preOderVisit();
}// Of if
}// Of preOrderVisit
/**
* **********************************
* In-order visit.
* **********************************
*/
public void inOderVisit() {
if(leftChild != null) {
leftChild.preOderVisit();
}// Of if
System.out.println("" + value + "");
if(rightChild != null) {
rightChild.preOderVisit();
}// Of if
}// Of inOrderVisit
/**
* *********************************
* Post-order visit.
* *********************************
*/
public void postOrderVisit() {
if(leftChild != null) {
leftChild.preOderVisit();
}// Of if
if(rightChild != null) {
rightChild.preOderVisit();
}// Of if
System.out.println("" + value + "");
}// Of postOrderVisit
/**
* **********************************
* Get the depth of the binary tree.
*
* @return The depth. It is 1 if there is only one code, i.e., the root.
* **********************************
*/
public int getDepth() {
// It is a leaf.
if (leftChild == null && rightChild == null) {
return 1;
}// Of if
//Only rightChild.
if (leftChild == null) {
return rightChild.getDepth() + 1;
}
//Only leftChild.
if (rightChild == null) {
return leftChild.getDepth() + 1;
}
//Both rightChild and leftChild.
if(leftChild.getDepth() > rightChild.getDepth()) {
return leftChild.getDepth() + 1;
} else {
return rightChild.getDepth() + 1;
}// Of if
}// Of depth
/**
* ***********************************
* Get the number of the nodes.
*
* @return The number of nodes.
* ***********************************
*/
public int getNumNodes() {
// It is a leaf.
if(leftChild == null && rightChild == null) {
return 1;
}// Of if
//Only rightChild.
if (leftChild == null) {
return rightChild.getNumNodes() + 1;
}
//Only leftChild.
if (rightChild == null) {
return leftChild.getNumNodes() + 1;
}
//Both rightChild and leftChild.
return leftChild.getNumNodes() + rightChild.getNumNodes() + 1;
}
/**
* **************************
* Convert the tree to data arrays, including a char array and an int array.
* The results are stored in two number variables.
*
* @see #valuesArray
* @see #indicesArray
* **************************
*/
public void toDataArrays() {
//Initialize arrays.
int tempLength = getNumNodes();
valuesArray = new char[tempLength];
indicesArray = new int[tempLength];
int i = 0;
//Traverse and convert at the same time.
CircleObjectQueue tempQueue = new CircleObjectQueue();
tempQueue.enqueue(this);
CircleIntQueue tempIntQueue = new CircleIntQueue();
tempIntQueue.enqueue(0);
BinaryCharTree tempTree = (BinaryCharTree) tempQueue.dequeue();
int tempIndex = tempIntQueue.dequeue();
while(tempTree != null) {
valuesArray[i] = tempTree.value;
indicesArray[i] = tempIndex;
i++;
if (tempTree.leftChild != null) {
tempQueue.enqueue(tempTree.leftChild);
tempIntQueue.enqueue(tempIndex * 2 + 1);
}// Of if
if (tempTree.rightChild != null) {
tempQueue.enqueue(tempTree.rightChild);
tempIntQueue.enqueue(tempIndex * 2 + 2);
}// Of if
tempTree = (BinaryCharTree) tempQueue.dequeue();
tempIndex = tempIntQueue.dequeue();
}// Of while
}// Of toDataArray
/**
* ************************************
* The entrance of the program.
*
* @param args
* Not used now.
* ************************************
*/
public static void main(String args[]) {
BinaryCharTree tempTree = manualConstructTree();
System.out.println("\r\nPreorder visit:");
tempTree.preOderVisit();
System.out.println("\r\nInorder visit:");
tempTree.inOderVisit();
System.out.println("\r\nPostorder visit:");
tempTree.postOrderVisit();
System.out.println("\r\n\r\nThe depth is:" + tempTree.getDepth());
System.out.println("\r\n\r\nThe number of nodes is:" + tempTree.getNumNodes());
tempTree.toDataArrays();
System.out.println("The values are: " + Arrays.toString(tempTree.valuesArray));
System.out.println("The indices are: " + Arrays.toString(tempTree.indicesArray));
}// Of main
}// Of BinaryCharTree
22.3 运行结果
Day 23: 使用具有通用性的队列
23.1 代码
/**
* **************************
* Convert the tree to data arrays, including a char array and an int array.
* The results are stored in two number variables.
*
* @see #valuesArray
* @see #indicesArray
* **************************
*/
public void toDataArraysObjectQueue() {
int tempLength = getNumNodes();
CircleObjectQueue tempQueue = new CircleObjectQueue();
tempQueue.enqueue(this);
CircleObjectQueue tempIntQueue = new CircleObjectQueue();
Integer tempIndexInteger = Integer.valueOf(0);
tempIntQueue.enqueue(tempIndexInteger);
valuesArray = new char[tempLength];
indicesArray = new int[tempLength];
int i = 0;
BinaryCharTree tempTree = (BinaryCharTree)tempQueue.dequeue();
Integer tempIndex = (Integer)tempIntQueue.dequeue();
while(tempTree != null) {
valuesArray[i] = tempTree.value;
indicesArray[i] = tempIndex.intValue();
i++;
if (tempTree.leftChild != null) {
tempQueue.enqueue(tempTree.leftChild);
tempIndexInteger = Integer.valueOf(2 * i + 1);
tempIntQueue.enqueue(tempIndexInteger);
}// Of if
if (tempTree.rightChild != null) {
tempQueue.enqueue(tempTree.rightChild);
tempIndexInteger = Integer.valueOf(2 * i + 2);
tempIntQueue.enqueue(tempIndexInteger);
}// Of if
tempTree = (BinaryCharTree)tempQueue.dequeue();
tempIndex = (Integer)tempIntQueue.dequeue();
}// Of while
}// Of toDataArraysObjectQueue
23.2 运行结果
Day 24:二叉树的建立
1、在给对象数组的成员变量赋值时,出现如下问题:
错误代码:
BinaryCharTree[] tempAllNodes = new BinaryCharTree[tempNumNodes]
tempAllNodes[i].value = paraDataArray[i];
正确代码:
BinaryCharTree[] tempAllNodes = new BinaryCharTree[tempNumNodes]
tempAllNodes[i] = new BinaryCharTree(paraDataArray[i]);
错误原因:
在定义对象数组时,只定义了null,在给对象赋值时,还需要用构造函数定义对象才可以。
2、在第二步,在二叉树结点之间建立关系时,使用单层循环,未能实现。调试时发现错误。
3、这个过程整个的思路其实和手动建立二叉树一致。
24.1 代码实现
/**
* *************************
* The second constructor. The parameters must be correct since no validity.
* Check is undertaken.
*
* @param paraDataArray The array for data.
* @param paraIndicesArray The array for indices.
* *************************
*/
public BinaryCharTree(char[] paraDataArray, int[] paraIndicesArray) {
int tempNumNodes = paraDataArray.length;
//Step 1. Construct all nodes. The first node is root.
BinaryCharTree[] tempAllNodes = new BinaryCharTree[tempNumNodes];
for (int i = 0; i < tempNumNodes; i++) {
//tempAllNodes[i].value = paraDataArray[i];
tempAllNodes[i] = new BinaryCharTree(paraDataArray[i]);
}// Of for i
//Step 2. Link all nodes.
for (int i = 1; i < tempNumNodes; i++) {
for(int j = 0; j < i; j++) {
if (paraIndicesArray[i] == paraIndicesArray[j] * 2 + 1) {
tempAllNodes[j].leftChild = tempAllNodes[i];
break;
} else if (paraIndicesArray[i] == paraIndicesArray[j] * 2 + 2){
tempAllNodes[j].rightChild = tempAllNodes[i];
break;
}// Of if
}// Of for j
}// Of for i
//Step 3. The root is the first node.
value = tempAllNodes[0].value;
leftChild = tempAllNodes[0].leftChild;
rightChild = tempAllNodes[0].rightChild;
}// Of the second constructor
24.2 运行结果
Day 25:二叉树深度遍历的栈实现(中序)
1、将char类型的变量 ch,存入Object 类型的栈中,需要进行如下操作:
其中方法1和方法2原理相同,将基本数据类型char 转换为Character 对象,方法2 由于版本更新被弃用。方法三中,默认将char 类型自动封箱为Character 。
- tempObjectStack.push(Character.valueOf(ch));
- tempObjectStack.push(new Character(ch));
- tempObjectStack.push(ch);
2、Character 和 char 的区别:
Character是char的包装类,就像Integer和int,包装类和基本类型可以自动转换叫自动封箱和自动解封。
char ch='a';
Character ch1=ch;//自动封箱
Character c=new Character(a);
char c1=c;//自动解封
3、面向对象中this 的用法 ,还没看懂。
4、中序遍历栈实现部分,有点没想明白。
25.1 对象栈代码实现
package datastructure.stack;
public class ObjectStack {
/**
* The depth.
*/
public static final int MAX_DEPTH = 10;
/**
* The actual depth.
*/
int depth;
/**
* The data.
*/
Object[] data;
/**
* ***************
* Construct an empty sequential list.
* ***************
*/
public ObjectStack() {
depth = 0;
data = new Object[MAX_DEPTH];
}// Of the first constructor
/**
* ********************
* Override the method claimed in Object, the superclass of any class.
* ********************
*/
public String toString() {
String resultString = "";
for (int i = 0; i < depth; i++) {
resultString += data[i];
}// Of for i
return resultString;
}
/**
* *********************
* Push an element.
*
* @param paraObject
* The given Object.
* @return Success or not.
* ********************
*/
public boolean push(Object paraObject) {
if(depth == MAX_DEPTH) {
System.out.println("The Object stack is full!");
return false;
}
data[depth] = paraObject;
depth++;
return true;
}// Of push
/**
* ************************
* Pop an element.
*
* @return The Object at the top of the stack.
* ************************
*/
public Object pop() {
if(depth == 0) {
System.out.println("Nothing to pop!");
return null;
}// Of if
Object reultObject = data[depth - 1];
depth--;
return reultObject;
}// Of pop
/**
* ************************
* Is the stack empty?
*
* @return True if empty.
* ************************
*/
public boolean isEmpty() {
if(depth == 0) {
System.out.println("The stack is empty!");
return true;
} else {
return false;
}// Of if
}// Of isEmpty
/**
* ***********************
* The entrance of program.
*
* @param args
* Not used now.
* ***********************
*/
public static void main(String[] args) {
ObjectStack tempObjectStack = new ObjectStack();
for(int i = 0; i < 5; i++) {
tempObjectStack.push(Integer.valueOf(i+10));
tempObjectStack.push(i+10);
}// Of for i
System.out.println("The current stack is:" + tempObjectStack.toString());
for(char ch = 'a'; ch < 'f'; ch++) {
tempObjectStack.push(Character.valueOf(ch));
//tempObjectStack.push(ch);
//tempObjectStack.push(new Character(ch));
}// Of for ch
System.out.println("The current stack is:" + tempObjectStack.toString());
}// Of main
}// Of ObjectStack
25.2 对象栈运行结果
25.3 中序遍历栈实现
/**
* ****************************
* In-order visit with stack.
* ****************************
*/
public void inOrderWithStack() {
ObjectStack tempStack = new ObjectStack();
BinaryCharTree tempNode = this;
while (!tempStack.isEmpty() || tempNode != null) {
if (tempNode != null) {
tempStack.push(tempNode);
tempNode = tempNode.leftChild;
} else {
tempNode = (BinaryCharTree) tempStack.pop();
System.out.println("" + tempNode.value + "");
tempNode = tempNode.rightChild;
}// Of if
}// Of while
}// Of inOrderWithStack
25.4 中序遍历栈实现运行结果
Day 26: 深度遍历的栈实现(前序和后序)
后序遍历中,问题的等价转换思路,太神奇了!
26.1 代码实现
/**
* ****************************
* Pre-order visit with stack.
* ****************************
*/
public void preOrderWithStack() {
ObjectStack tempStack = new ObjectStack();
BinaryCharTree tempNode = this;
while (!tempStack.isEmpty() || tempNode != null) {
if (tempNode != null) {
tempStack.push(tempNode);
System.out.println("" + tempNode.value + "");
tempNode = tempNode.leftChild;
} else {
tempNode = (BinaryCharTree) tempStack.pop();
tempNode = tempNode.rightChild;
}// Of if
}// Of while
}// Of preOrderWithStack
/**
* ****************************
* Post-order visit with stack.
* ****************************
*/
public void postOrderWithStack() {
ObjectStack tempStack = new ObjectStack();
BinaryCharTree tempNode = this;
ObjectStack tempOutputStack = new ObjectStack();
while (!tempStack.isEmpty() || tempNode != null) {
if (tempNode != null) {
//Store for output.
tempStack.push(tempNode);
tempOutputStack.push(tempNode.value);
tempNode = tempNode.rightChild;
} else {
tempNode = (BinaryCharTree) tempStack.pop();
tempNode = tempNode.leftChild;
}// Of if
}// Of while
//Now reverse output.
while (!tempOutputStack.isEmpty()) {
System.out.println(" " + tempOutputStack.pop() + " ");
}// Of while
}// Of postOrderWithStack
26.2 运行结果
Day 27:Hanoi 问题
在运行程序时,报错栈溢出,找了半天错误,原来是在结束条件时,忘记写return。
27.1 代码
package datastructure.tree;
/**
* Hanoi tower.
* @author XuQiong
*
*/
public class Hanoi {
/**
* **********************
* Move a number of plates.
*
* @param paraSource
* The source pole.
* @param paraIntermedium
* The intermediary pole.
* @param paraDestination
* The destination pole.
* @param paraNumber
* The number of plates.
* **********************
*/
public static void hanoi(char paraSource, char paraIntermediary, char paraDestination,
int paraNumber) {
if(paraNumber == 1) {
System.out.println(paraSource + " -> " + paraDestination);
return;
}// Of if
hanoi(paraSource, paraDestination, paraIntermediary, paraNumber - 1);
System.out.println(paraSource + " -> " + paraDestination);
hanoi(paraIntermediary, paraSource, paraDestination, paraNumber - 1);
}// Of hanoi
/**
* *************************
* The entrance of program.
*
* @param args
* Not used now.
* *************************
*/
public static void main(String args[]) {
hanoi('a', 'b', 'c', 3);
}// Of main
}// Of class Hanoi
27.2 运行结果
Day 28: Huffman 编码(结点定义与文件读取)
1、异常处理,参考知乎 用不秃头的码农
两种方式:
- try/catch
- throws
-
public class ExceptionTest{ public void readFile() { try { FileInputStream fileInputStream=new FileInputStream("xxx.text"); } catch (FileNotFoundException e) { e.printStackTrace(); }finally { } } }
-
public class ExceptionTest{ public void readFile() throws FileNotFoundException { FileInputStream fileInputStream=new FileInputStream("xxx.text"); } }
-
差异在于,try/catch捕获到异常后直接在catch语句里进行处理,处理完成之后程序继续往下执行。而throws则是将异常抛给它的上一级进行解决,程序就不再往下执行了。
使用catch捕获到异常之后,我们可以对异常进行处理,常见的方式就是将异常打印出来或者写入到日志里。下面是Throwable类中的常用方法。
public String getMessage() //返回异常的简要信息
public String getLocalizedMessage() //返回异常的本地化信息,默认和getMessage是一样的,如果要加入本地化信息往往是子类重写这个方法
public String toString() //返回异常的更详细信息
public void printStackTrace() //在控制台输出异常信息。
try/catch之后往往还会更finally语句,finally语句中的代码会在程序处理完成最后被执行,不管是否进入异常。如果在代码中有return语句,在return执行之前,finally语句中的代码会被先执行。 finally 语句的返回值将会覆盖原始的返回值。
Day 29: Huffman 编码 (建树)
29.1 代码
package datastructure.tree;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
* Huffman tree, encoding, and decoding. For simplicity, only ASCII characters
* are supported.
*
* @author XuQiong
*/
public class Huffman {
/**
* An inner class for Huffman nodes.
*/
class HuffmanNode {
/**
* The char. Only valid for leaf nodes.
*/
char character;
/**
* Weight. It can also be double.
*/
int weight;
/**
* The left child.
*/
HuffmanNode leftChild;
/**
* The right child.
*/
HuffmanNode rightChild;
/**
* The parent. It helps constructing the huffman code of each character.
*/
HuffmanNode parent;
/**
* ***************************
* The first constructor.
* ***************************
*/
public HuffmanNode(char paraCharacter, int paraWeight, HuffmanNode paraLeftChild,
HuffmanNode paraRightChild, HuffmanNode paraParent) {
character = paraCharacter;
weight = paraWeight;
leftChild = paraLeftChild;
rightChild = paraRightChild;
parent = paraParent;
}// Of HuffmanNode
/**
* ***************************
* To string.
* ***************************
*/
public String toString() {
String resultString = "(" + character + ", " + weight + ")";
return resultString;
}// Of toString
}// Of class HuffmanNode
/**
* The number of characters. 256 for ASCII.
*/
public static final int NUM_CHARS = 256;
/**
* The input text. It is stored in a string for simplicity.
*/
String inputText;
/**
* The length of the alphabet, also the number of leaves.
*/
int alphabetLength;
/**
* The alphabet;
*/
char[] alphabet;
/**
* The count of chars. The length is 2 * alphabetLength - 1 to include
* non-leaf nodes.
*/
int[] charCounts;
/**
* The mapping of chars to the indices in the alphabet.
*/
int[] charMapping;
/**
* Codes for each char in the alphabet. It should have the same length as
* alphabet.
*/
String[] huffmanCodes;
/**
* All nodes. The last node is the root.
*/
HuffmanNode[] nodes;
/**
* ***************************
* The first constructor.
*
* @param paraFilename.
* The text filename.
* ***************************
*/
public Huffman(String paraFilename) {
charMapping = new int[NUM_CHARS];
readText(paraFilename);
}
/**
* ****************************
* Read text.
*
* @param paraFilename
* The text filename.
* ****************************
*/
public void readText(String paraFilename) {
try {
inputText = Files.newBufferedReader(Paths.get(paraFilename), StandardCharsets.UTF_8)
.lines().collect(Collectors.joining("\n"));
} catch (Exception ee) {
System.out.println(ee);
System.exit(0);
}// Of try
System.out.println("The text is: \r\n" + inputText);
}// Of readText
/**
* ******************************
* Construct the alphabet. The results are stored in the member variables
* charMapping and alphabet.
* ******************************
*/
public void constructAlphabet() {
//Initialize.
Arrays.fill(charMapping, -1);
//The count for each char. At most NUM_CHARS chars.
int[] tempCharCounts = new int[NUM_CHARS];
//The index of the char in the ASCII charset.
int tempCharIndex;
//Step 1. Scan the string to obtain the counts.
char tempChar;
for (int i = 0; i < inputText.length(); i++) {
tempChar = inputText.charAt(i);
tempCharIndex = (int)tempChar;
System.out.println("" + tempCharIndex + "");
tempCharCounts[tempCharIndex]++;
} // Of for i
//Step 2. Scan to determine the size of alphabet.
alphabetLength = 0;
for (int i = 0; i < 255; i++) {
if(tempCharCounts[i] > 0) {
alphabetLength++;
}// Of if
}// Of for i
//Step 3. Compress to the alphabet.
alphabet = new char[alphabetLength];
charCounts = new int[2 * alphabetLength - 1];
int tempCounter = 0;
for (int i = 0; i < NUM_CHARS; i++) {
if(tempCharCounts[i] > 0) {
alphabet[tempCounter] = (char) i;
charCounts[tempCounter] = tempCharCounts[i];
charMapping[i] = tempCounter;
tempCounter++;
}// Of if;
}// Of for i;
System.out.println("The alphabet is: " + Arrays.toString(alphabet));
System.out.println("Their counts are: " + Arrays.toString(charCounts));
System.out.println("The char mapping are: " + Arrays.toString(charMapping));
}// Of contructAlphabet
/**
* *****************************
* Construct the tree.
* *****************************
*/
public void 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 ofr i
//Step 3. Construct the tree.
int tempLeft, tempRight, tempMinimal;
for(int i = alphabetLength; i < 2* alphabetLength; 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
}// 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(tempMinimal > charCounts[j]) {
tempMinimal = charCounts[j];
tempRight = j;
}// Of if
}// Of for j
tempProcessed[tempRight] = true;
System.out.println("Selecting " + 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
}// Of constructTree
/**
* ******************************
* Get the root of the binary tree.
*
* @return The root.
* ******************************
*/
public HuffmanNode getRoot() {
return nodes[nodes.length - 1];
}// Of getRoot
/**
* ******************************
* The entrance of program.
*
* @param args
* Not used now.
* ******************************
*/
public static void main(String args[]) {
Huffman tempHuffman = new Huffman("E:/Java/Java_sampledata/huffmantext.txt");
tempHuffman.constructAlphabet();
tempHuffman.constructTree();
}// Of main
}// Of class Huffman