poj-1521

来源:互联网 发布:java最新版本下载 编辑:程序博客网 时间:2024/04/29 18:50
// 3068K 282MSJava
import java.util.Collections;
import java.util.List; 
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Comparator;
import java.util.Arrays;


public class Main {
private static final int MAX = 27;
private static final char UNDER_SCORE = '_';


private class CharacterComparator implements Comparator<CharacterTreeNode> {
@Override
   public int compare(CharacterTreeNode o1, CharacterTreeNode o2) {
       return o1.num - o2.num;
   }
}


private CharacterComparator mComparator;


private int[] mCharacterMap;


private int mStrLength;


// private class Character {
// public char content;
// public int num;
// public boolean isParentNode;
// }


private class CharacterTreeNode {
public CharacterTreeNode left;
public CharacterTreeNode right;
public int num;
public char content ;
};


private int mCharType;


private CharacterTreeNode[] mCharacterInfo;


public void preProcess(String str) {
for (int i = 0; i < MAX; i++) {
mCharacterInfo[i] = new CharacterTreeNode();
mCharacterInfo[i].left = null;
mCharacterInfo[i].right = null;
}
mStrLength = str.length();
for (int i = 0; i < MAX; i++) {
mCharacterMap[i] = 0;
}
byte[] byteArray = str.getBytes();


for (int i = 0; i < mStrLength; i++) {
if (byteArray[i] == UNDER_SCORE) {
mCharacterMap[MAX-1]++;
} else {
mCharacterMap[byteArray[i]-'A']++;
}
}


for (int i = 0; i < MAX-1; i++) {
if (mCharacterMap[i] != 0) { // this char appear
mCharacterInfo[mCharType].content = (char)(i + 'A');
mCharacterInfo[mCharType++].num = mCharacterMap[i];
}
}
if (mCharacterMap[MAX-1] != 0) {
mCharacterInfo[mCharType].content = '_';
mCharacterInfo[mCharType++].num = mCharacterMap[MAX-1];
}
}


private int mOptinalLength;


public void bypassTree(CharacterTreeNode node, int degree) {
if (node == null) {
return;
}
if (node.left == null && node.right == null) {
// System.out.println(node.content + " " + degree);
mOptinalLength += (degree-1)*(node.num);
} else {
bypassTree(node.left, degree + 1);
bypassTree(node.right, degree + 1);
}
}


public void solve(String str) {
mOptinalLength = 0;
mCharType = 0;
preProcess(str);
int treeNodeNum = mCharType;
while(treeNodeNum > 1) {
Arrays.sort(mCharacterInfo, 0, treeNodeNum, mComparator);
CharacterTreeNode leftTreeNode = mCharacterInfo[0];
CharacterTreeNode rightTreeNode = mCharacterInfo[1];
CharacterTreeNode sumTreeNode = new CharacterTreeNode();
sumTreeNode.num = leftTreeNode.num + rightTreeNode.num;
sumTreeNode.left = leftTreeNode.num < rightTreeNode.num ?
leftTreeNode : rightTreeNode;
sumTreeNode.right = leftTreeNode.num >= rightTreeNode.num ?
leftTreeNode : rightTreeNode;
mCharacterInfo[0] = sumTreeNode;
if (treeNodeNum > 2) {
mCharacterInfo[1] = mCharacterInfo[treeNodeNum-1];
}
treeNodeNum--;
}


bypassTree(mCharacterInfo[0], 1);
int orginalLength = mStrLength * 8;
if (mCharType == 1) {
mOptinalLength = mStrLength;
}
// java.text.DecimalFormat df = new java.text.DecimalFormat("#.#");
String result = String.format("%.1f", (double)orginalLength/mOptinalLength);
// System.out.println(orginalLength + " " + mOptinalLength + " " + ((int)(((double)orginalLength)/mOptinalLength*10))/10.0);
System.out.println(orginalLength + " " + mOptinalLength + " " + result);
}


public Main() {
mCharType = 0;
mOptinalLength = 0;
mCharacterInfo = new CharacterTreeNode[MAX];
for (int i = 0; i < MAX; i++) {
mCharacterInfo[i] = new CharacterTreeNode();
mCharacterInfo[i].left = null;
mCharacterInfo[i].right = null;
}
mComparator = new CharacterComparator();
mCharacterMap = new int[MAX];
}


public static void main(String[] args) {
Main solver = new Main();
Scanner input = new Scanner(System.in);
while(true) {
String str = input.next();
if (str.equals("END")) {
return;
}
solver.solve(str);
}


}

}

 3068K 282MSJava

纯哈弗曼树水题,复习了下如何构造哈弗曼树。

两个注意:

1: 注意只有一种字母的情况,这种情况下哈弗曼树不适用

2: java的一定要注意,题目虽然没说四舍五入,但其实是要求四舍五入的,WA了好几次....


没有用优先级队列,为了继续训练java的基础操作,用的是每次合并完重新排序,每次合并完前两个节点,把第一个节点更新为合并出来的节点,第二个节点则和

队列最后一个节点互换(java全引用就是好,直接指过去就完了,如果只有两个节点,就不用了),下次重新排序,只不过范围-1. 直到最后只剩一个节点退出。

最后遍历形成的树,在每个叶子节点(每个要编码字符)计算其树高和个数的乘积,累加即可。

mark一下,以后再写个用了优先队列的版本.

0 0
原创粉丝点击