//对字符串进行操作的时候,要考虑大小写;
//霍夫曼编码,把待编码文本赋值给str,便可输出对字母以及空格“,”字符的编码
public class HuffCode{
public static void main(String [] args){
Random rand=new Random(47);
HuffNode huffRoot=new HuffNode(new HuffData());
double [] dArr=new double [28];
HuffNode [] nArr=new HuffNode [28];
// String str="Hello my name is ShangYunlei my girl friend is YiMing";
// String str="In the traffic court of a large mid-western city, a young lady was brought before the judge to answer a ticket given her for driving through a red light. She explained to his honor that she was a school teacher and requested an immediate disposal of her case in order that she might hasten on to her classes. A wild gleam came into the judge's eye. You are a school teacher, eh? said he. Madam, I shall realize my lifelong ambition. Sit down at that table and write I went through a red light five hundred times.";
String str="abcdefghijklmnopqrstuvwxyz ,";
System.out.println(str.length());
//计算文本中字母(忽略大小写), “ ”, “,” 出现的概率
dArr=frequencyCalculate(str);
//用HuffNode将字符与其出现的概率联系起来
for(int i=0; i<dArr.length-2; i++){
nArr[i]=new HuffNode(new HuffData((char)('A'+i), dArr[i]));
}
nArr[nArr.length-2]=new HuffNode(new HuffData(' ', dArr[dArr.length-2]));
nArr[nArr.length-1]=new HuffNode(new HuffData(',', dArr[dArr.length-1]));
//通过优先级队列建立霍夫曼树
for(int i=0; i<dArr.length; i++) nArr[i].display();
PQueue que=new PQueue(nArr.length);
for(int i=0; i<nArr.length; i++) que.insert(nArr[i]);
que.display();
huffRoot=huffEstab(que);
//利用双栈逐层遍历法逐层遍历霍夫曼树,对相应的字符进行编码(left:0, right:1)
HuffTree huffTree=new HuffTree();
huffTree.root=huffRoot;
System.out.println("InOrder Transverse:");
huffTable(huffTree);
//以String [] 形式保存字符对应的编码
System.out.println("HuffTable");
String [] sArr=new String[28];
huffTree.inOrderTransverse(sArr);
for(int i=0; i<sArr.length-2; i++) System.out.println((char)('A'+i)+" has been coded: "+sArr[i]);
System.out.println(" has been coded: "+sArr[26]);
System.out.println(", has been coded: "+sArr[27]);
//遍历文本进行编码
String oString=new String();
for(int i=0; i<str.length(); i++){
if(str.charAt(i)>='A' && str.charAt(i)<='Z') oString+=sArr[str.charAt(i)-'A'];
else if(str.charAt(i)>='a' && str.charAt(i)<='z') oString+=sArr[str.charAt(i)-'a'];
else if(str.charAt(i)==',') oString+=sArr[27];
else if(str.charAt(i)==' ') oString+=sArr[26];
}
System.out.println(oString);
}
public static HuffNode huffEstab(PQueue que){
// HuffNode t=new HuffNode(new HuffData());
while(que.number()>1){
HuffNode t=new HuffNode(new HuffData());
t.left=que.remove();
t.right=que.remove();
t.d.context='!';
t.d.freq=t.left.d.freq+t.right.d.freq;
que.insert(t);
}
return que.remove();
}
public static void huffTable(HuffTree tree){
HuffStack cStack=new HuffStack(100);
HuffStack pStack=new HuffStack(100);
boolean flag=true;
tree.root.left.d.code="0";
tree.root.right.d.code="1";
cStack.push(tree.root.left);
cStack.push(tree.root.right);
while(flag){
flag=false;
while(!cStack.isEmpty()){
pStack.push(cStack.pop());
}
while(!pStack.isEmpty()){
HuffNode node=pStack.pop();
node.left.d.code=node.d.code;
node.right.d.code=node.d.code;
node.left.d.code+="0";
if(node.left.d.context=='!'){
cStack.push(node.left);
flag=true;
}
node.right.d.code+="1";
if(node.right.d.context=='!'){
cStack.push(node.right);
flag=true;
}
}
}
}
public static double [] frequencyCalculate(String str){
int [] iArr=new int [28];
double [] dArr=new double[28];
for(int i=0; i<str.length(); i++){
if(str.charAt(i)==' ') iArr[26]++;
else if(str.charAt(i)==',') iArr[27]++;
else if(str.charAt(i)>='A' && str.charAt(i)<='Z') iArr[str.charAt(i)-'A']++;
else if(str.charAt(i)>='a' && str.charAt(i)<='z') iArr[str.charAt(i)-'a']++;
}
int sum=0;
for(int i=0; i<iArr.length; i++) sum+=iArr[i];
for(int i=0; i<iArr.length; i++) dArr[i]=(double)iArr[i]/(double)sum;
return dArr;
}
}
class HuffNode{
public HuffData d;
public HuffNode left;
public HuffNode right;
public HuffNode(){
d=new HuffData();
left=null;
right=null;
}
public HuffNode(HuffData d){
this.d=d;
left=null;
right=null;
}
public void display(){
System.out.println(d.context+", "+d.freq+", "+d.code);
}
}
class HuffData{
public char context;
public double freq;
public String code;
public HuffData(){
context='!';
freq=0.0;
code=null;
}
public HuffData(char context, double freq){
this.context=context;
this.freq=freq;
code=null;
}
}
class HuffStack{
private HuffNode [] nArr;
private int max, current;
public HuffStack(){
nArr=null;
max=0;
current=0;
}
public HuffStack(int max){
this.max=max;
nArr=new HuffNode[max];
for(int i=0; i<max; i++) nArr[i++]=new HuffNode();
current=0;
}
public void push(HuffNode node){
if(this.isFull()) System.out.println("The Stack is Full. ");
else nArr[current++]=node;
}
public HuffNode pop(){
return nArr[--current];
}
public int depth(){
return current;
}
public HuffNode peek(){
return nArr[current-1];
}
public boolean isEmpty(){
return current==0;
}
public boolean isFull(){
return current==max;
}
}
class PQueue{
private HuffNode [] nArr;
private int max;
private int current;
public PQueue(int max){
this.max=max;
nArr=new HuffNode [max];
for(int i=0; i<max; i++) nArr[i]=null;
current=0;
}
public void insert(HuffNode n){
int i=current-1;
if(this.isFull()){System.out.println("This Queue is Full! "); return;}
for(; i>=0 && nArr[i].d.freq<n.d.freq; i--) nArr[i+1]=nArr[i];
nArr[i+1]=n;
current++;
}
public int number(){
return current;
}
public HuffNode remove(){
return nArr[--current];
}
public HuffNode peek(){
return nArr[current-1];
}
public boolean isEmpty(){
return (current==0);
}
public boolean isFull(){
return (current==max);
}
public void display(){
for(int i=0; i<current; i++) System.out.println("['"+nArr[i].d.context+"', "+nArr[i].d.freq+"] ");
System.out.println();
}
}
class HuffTree{
public HuffNode root;
public HuffTree(){
root=null;
}
public HuffTree(HuffNode root){
this.root=root;
}
public void inOrderTransverse(String [] sArr){
inOrder(root, sArr);
}
public void inOrder(HuffNode n, String [] sArr){
if(n==null) return;
else{
inOrder(n.left, sArr);
if(n.d.context!='!'){
if(n.d.context>='A' && n.d.context<='Z') sArr[n.d.context-'A']=n.d.code;
else if(n.d.context==' ') sArr[26]=n.d.code;
else if(n.d.context==',') sArr[27]=n.d.code;
}
inOrder(n.right, sArr);
}
}
}