之前在《信息论与编码》这个课程的实验里写过生成Huffman编码的实验,那个时候用Scanner创建的in没有关闭(当时没有察觉我应该用close
方法关闭),今天突然看到eclipse那个刺眼的警告图标,于是有点强迫症,准备把它关掉。
但是呢,遇到了一点小问题,就是最开始我想的是直接在最下面写一句in.close();
就ok,然而这样做之后发现他并没有关掉。经过仔细观察之后发现是我在输入信源符号和概率分布之后对非法输入进行了终止程序的处理(顺便吐槽下愚蠢的自己总是学不会用状态机进行输入检测)。我用的是return;
这一句来终止程序,当然在它前面也输出了错误的原因,不过我却没有在每次return;
之前都写in.close();
关闭,所以才会有警告。所以应该在每个return;
语句前加上in.close();
,经测试发现警告消失,以后编程一定要细心。
附上生成Huffman编码的代码:
import java.util.Scanner;
import huffman.HuffmanCode.*;
/**
*@author movis
*/
public class Main {
//对输入输出的控制
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入信源符号个数q:");
int n = in.nextInt();
int m = 2*n - 1;
//对输入不正确的信号,打印错误信息,并直接结束程序
if(n <= 1) {
System.out.println("输入信源符号个数不正确");
in.close();
return ;
}
Node[] huffmanTree = new Node[m];
NodeCode[] huffmanCode = new NodeCode[n];
HuffmanCode.initHuffmanTree(huffmanTree, m);
HuffmanCode.initHuffmanCode(huffmanCode, n);
System.out.println("请输入信源符号s(0)-s(q-1):");
for(int i=0; i 0 ) {
HuffmanCode.getHuffmanp(huffmanTree, i, temp2[i]);
sum += temp2[i];
System.out.println(i+":sum:"+sum);
}
else {
System.out.println("输入概率值不为小于1的正数,输入错误");
in.close();
return;
}
}
//对概率和进行处理,只允许概率和为1
System.out.println(sum);
if(sum != 1) {
System.out.println("概率之和不为1");
in.close();
return;
}
//创建huffmanTree
HuffmanCode.createHaffmanTree(huffmanTree,n);
//创建huffmanCode
HuffmanCode.createHaffmanCode(huffmanTree,huffmanCode,n);
//打印字符与编码的对应关系
System.out.println("字符与编码的对应关系如下:");
for(int i=0;i
/**
* @author movis
*/
public class HuffmanCode {
//建立Huffman树节点
static class Node {
double p;
int root;
int left;
int right;
public Node(double p, int root, int left, int right) {
this.p = p;
this.root = root;
this.left = left;
this.right = right;
}
void setp(double p) {
this.p = p;
}
void setroot(int root) {
this.root = root;
}
void setleft(int left) {
this.left = left;
}
void setright(int right) {
this.right = right;
}
double getp() {
return p;
}
int getroot() {
return root;
}
int getleft() {
return left;
}
int getright() {
return right;
}
}
//新建Huffman编码
static class NodeCode {
String character;
String code;
NodeCode(String character, String code) {
this.character = character;
this.code = code;
}
NodeCode(String code) {
this.code = code;
}
void setCharacter(String character) {
this.character = character;
}
void setCode(String code) {
this.code = code;
}
String getCharacter() {
return character;
}
String getCode() {
return code;
}
}
//初始化一个huffmanTree
public static void initHuffmanTree(Node[] huffmanTree, int m) {
for (int i = 0; i < m; i++)
huffmanTree[i] = new Node(0, -1, -1, -1);
}
//初始化一个huffmanCode
public static void initHuffmanCode(NodeCode[] huffmanCode, int n) {
for (int i = 0; i < n; i++)
huffmanCode[i] = new NodeCode("", "");
}
//获取huffmanCode的符号
public static void getHuffmanCode(NodeCode[] huffmanCode, int i, String temp) {
huffmanCode[i] = new NodeCode(temp, "");
}
//获取huffmanTree节点频率
public static void getHuffmanp(Node[] huffmanTree, int i, double temp) {
huffmanTree[i] = new Node(temp, -1, -1, -1);
}
//从n个节点中选取最小的两个节点
public static int[] selectMin(Node[] huffmanTree, int n) {
int min[] = new int[2];
class TempNode {
//存储权重
double newp;
//存储该结点所在的位置
int place;
TempNode(double newp, int place) {
this.newp = newp;
this.place = place;
}
double getNewp() {
return newp;
}
int getPlace() {
return place;
}
}
TempNode[] tempTree = new TempNode[n];
//将huffmanTree中没有双亲的结点存储到tempTree中
int i = 0, j = 0;
for (i = 0; i < n; i++) {
if (huffmanTree[i].getroot() == -1 && huffmanTree[i].getp() != 0) {
tempTree[j] = new TempNode(huffmanTree[i].getp(), i);
j++;
}
}
int m1, m2;
m1 = m2 = 0;
for (i = 0; i < j; i++) {
//此处不让取到相等,是因为结点中有相同权值的时候,m1取最前的
if (tempTree[i].getNewp() < tempTree[m1].getNewp())
m1 = i;
}
for (i = 0; i < j; i++) {
if (m1 == m2)
//当m1在第一个位置的时候,m2向后移一位
m2++;
//此处取到相等,是让在结点中有相同的权值的时候,m2取最后的那个
if (tempTree[i].getNewp() <= tempTree[m2].getNewp() && i != m1)
m2 = i;
}
min[0] = tempTree[m1].getPlace();
min[1] = tempTree[m2].getPlace();
return min;
}
//创建huffmanTree
public static void createHaffmanTree(Node[] huffmanTree, int n) {
int m = 2 * n - 1;
for (int i = n; i < m; i++) {
int[] min = selectMin(huffmanTree, i);
int min1 = min[0];
int min2 = min[1];
huffmanTree[min1].setroot(i);
huffmanTree[min2].setroot(i);
huffmanTree[i].setleft(min1);
huffmanTree[i].setright(min2);
huffmanTree[i].setp(huffmanTree[min1].getp() + huffmanTree[min2].getp());
}
}
//创建huffmanCode
public static void createHaffmanCode(Node[] huffmanTree, NodeCode[] huffmanCode, int n) {
char[] code = new char[10];
int start;
int c;
int root;
code[n - 1] = '0';
for (int i = 0; i < n; i++) {
StringBuffer stringBuffer = new StringBuffer();
start = n - 1;
c = i;
while ((root = huffmanTree[c].getroot()) >= 0) {
start--;
//左边0右边1
code[start] = ((huffmanTree[root].getleft() == c) ? '0' : '1');
c = root;
}
for (; start < n - 1; start++) {
stringBuffer.append(code[start]);
}
huffmanCode[i].setCode(stringBuffer.toString());
}
}
}