大文件M包含许多字符,它们是'a','b','c','d','e','f','g'中的一个,每个富裕唯一编码
1.使用了优先级队列Heap
2.定义接口PriorityQueue
3。改程序限定在祖父记得256个字符之内,每个字符在ArrayList数组中都有一个对应的位置,例如,’B‘,该字符的信息被存储在索引(int)'B'处,即66.详见代码和附件
code:
package Exercize;
public interface PriorityQueue<E> {
int size() ;
boolean isEmpty() ;
void add(E element) ;
E getMin() ;
E removeMin() ;
}
package HUffman;
import Exercize.Heap ;
import Exercize.PriorityQueue;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class Huffman {
public final static int SIZE = 256 ;
protected Entry[] leafEntries ; //以字符ASC||为索引的数组
protected PriorityQueue<Entry> pq ;
public Huffman(){
Entry entry ;
leafEntries = new Entry[SIZE] ;
for(int i = 0; i < SIZE; i ++)
{
leafEntries[i] = new Entry() ;
entry = leafEntries[i] ;
entry.freq = 0 ;
entry.left = null ;
entry.right = null ;
entry.parent = null ;
}
pq = new Heap<Entry>() ;
}
public void updateFrequencies(String line){
Entry entry ;
for(int j = 0; j < line.length(); j ++)
{
entry = leafEntries[(int)(line.charAt(j))] ;
entry.freq ++ ;
}
entry = leafEntries[(int)'\r'] ; //保证消息原来的行结构在解码过程中保持不变
entry.freq ++ ;
}
//首先填充leafEntries对象,然后在此基础上填充优先级队列,按照频率递增的顺序插入
public void createPQ() throws IOException {
Entry entry ;
for(int i = 0 ; i < SIZE ; i ++){
entry = leafEntries[i] ;
if(entry.freq > 0)
pq.add(entry) ;
}
}
//频率最低的字符优先删除组成树的节点
public void createHuffmanTree(){
Entry left,
right,
sum ;
while(pq.size() > 1){
left = pq.removeMin() ;
left.code = "0" ;
right = pq.removeMin() ;
right.code = "1" ;
sum = new Entry() ;
sum.parent = null ;
sum.freq = left.freq + right.freq ;
sum.left = left ;
sum.right = right ;
left.parent = sum ;
right.parent = sum ;
pq.add(sum) ; //将左右子节点的频率之和成为其父节点,并添加到优先级队列中
}
}
//解码
public void calculateHuffmanCodes()
{
String code;
Entry entry;
for (int i = 0; i < SIZE; i++)
{
code = "";
entry = leafEntries [i];
if (entry.freq > 0)
{
while (entry.parent != null)
{
code = entry.code + code;
entry = entry.parent;
} // while
leafEntries [i].code = code;
} // if
} // for
} // calculateHuffmanCodes
public String getCodes()
{
Entry entry;
String codes = new String();
for (int i = 0; i < SIZE; i++)
{
entry = leafEntries [i];
if (entry.freq > 0)
codes += (char)i + " " + entry.code + "\n";
} // for
return codes;
} // method getCodes
public String getEncodedLine (String line)
{
Entry entry;
String encodedLine = new String();
for (int j = 0; j < line.length(); j++)
{
entry = leafEntries [(int)(line.charAt (j))];
encodedLine += entry.code;
} // for
entry = leafEntries [(int)'\r'];
encodedLine += entry.code;
return encodedLine;
} // method getEncodedLine
} // class Huffman
class Entry implements Comparable<Entry>
{
int freq;
String code;
char id;
Entry left,
right,
parent;
public int compareTo (Entry entry)
{
return freq - entry.freq;
} // compareTo
} // class Entry
package HUffman;
import java.io.*;
public class HuffmanTester
{
protected BufferedReader fileReader;
protected PrintWriter fileWriter;
protected Huffman huffman;
protected String inFilePath;
public HuffmanTester()
{
huffman = new Huffman();
} // default constructor
public PrintWriter openFiles()
{
final String IN_FILE_PROMPT =
"\nPlease enter the path for the input file: ";
final String OUT_FILE_PROMPT =
"\nPlease enter the path for the output file: ";
BufferedReader keyboardReader = new BufferedReader(new InputStreamReader (System.in));
String outFilePath,
line;
boolean pathsOK = false;
while (!pathsOK)
{
try
{
System.out.print (IN_FILE_PROMPT);
inFilePath = keyboardReader.readLine();
fileReader= new BufferedReader(new FileReader (inFilePath));
System.out.print (OUT_FILE_PROMPT);
outFilePath = keyboardReader.readLine();
fileWriter = new PrintWriter (new FileWriter (outFilePath));
pathsOK = true;
} // try
catch (IOException e)
{
System.out.println (e);
} // catch
} // while !pathOK
return fileWriter;
} // method openFiles
public void createEncoding()
{
String line;
try
{
while (true)
{
line = fileReader.readLine();
if (line == null)
break;
huffman.updateFrequencies (line);
} // while
fileReader.close(); // re-opened in saveEncodedMessage
huffman.createPQ();
huffman.createHuffmanTree();
huffman.calculateHuffmanCodes();
} // try
catch (IOException e)
{
System.out.println (e);
} // catch IOException
} // method createEncoding
public void saveEncodedMessage()
{
String line;
try
{
fileWriter.print (huffman.getCodes());
fileWriter.println ("**"); // to separate codes from encoded message
fileReader = new BufferedReader (new FileReader (inFilePath));
while (true)
{
line = fileReader.readLine();
if (line == null)
break;
fileWriter.println (huffman.getEncodedLine (line));
} // while
} // try
catch (IOException e)
{
System.out.println (e);
} // catch IOException
} // method saveEncodedMessage
} // class HuffmanTester
package HUffman;
import java.io.*;
public class HuffmanTesterMain {
public static void main(String[] args) {
PrintWriter writer = null;
try
{
HuffmanTester tester = new HuffmanTester();
writer = tester.openFiles();
tester.createEncoding();
tester.saveEncodedMessage();
} // try
finally
{
writer.close();
} // finally
}
}
输入字符的存储结构:
频率 |
编码 |
字符 |
parent |
left |
right |
分享到:
相关推荐
在C语言下实现哈弗曼树的创建并进行哈弗曼编码,同时输出哈弗曼编码。
6. **解压缩**:在解压时,读取存储的哈弗曼树或编码表,然后按照编码解码得到原始的字符流,再重新组合成原来的txt或doc文件。 在C++编程语言中实现哈弗曼编码,你需要定义数据结构来表示哈弗曼树节点,如包括字符...
5. **解码数据**:解码过程需要哈弗曼树和编码后的二进制数据。遍历二进制数据,每次根据当前位决定是向左还是向右移动,直到到达叶子节点,记录该叶子节点所代表的字符,并回到根节点继续解码剩余的二进制数据。 ...
在"霍夫曼编码"这个项目中,可能包含了实现这些功能的源代码文件,包括构造哈弗曼树、统计字符频率、生成哈弗曼编码和解码的算法。通过对这些代码的分析和学习,我们可以深入理解哈弗曼编码的工作原理,并能够实际...
根据给定文件的信息,我们可以总结出以下关于“哈弗曼树编码解码程序”的相关知识点: ### 一、概述 哈弗曼树(Huffman Tree)又称最优二叉树,是一种带权路径长度最短的二叉树。哈弗曼编码(Huffman Coding)是一...
构建哈弗曼树是整个编码过程的基础,具体步骤如下: 1. **初始化节点**:首先根据字符出现的频率初始化所有节点的权重,其余属性如左右子节点、父节点等设为0。 2. **选择与合并节点**:通过循环,每次选择两个...
5. **输入编码解码**: 解码时,需要再次遍历所有叶子节点,对输入的哈弗曼编码逐位与每个节点的编码进行比对。当输入编码与某个字符的哈弗曼编码完全匹配时,输出对应的字符。如果在比对过程中发现编码不匹配,...
在实际应用中,哈弗曼树可以与其他算法结合使用,例如 LZ77、LZW 等,以提高压缩比和编码速度。 在哈弗曼树的实现中,需要注意以下几点: * 需要选择合适的数据结构来存储哈弗曼树 * 需要合理地选择哈弗曼树的建立...
哈弗曼编码是一种高效的数据压缩方法,它基于一种特殊的二叉树——哈弗曼树(Huffman Tree),也称为最优二叉树。在MFC(Microsoft Foundation Classes)框架下,我们可以构建用户界面来实现哈弗曼编码和解码的过程...
哈弗曼树编码是一种高效的前缀编码方法,广泛应用于数据压缩和通信领域。在这个课程设计中,我们将深入探讨哈弗曼编码的原理、构建过程以及如何实现编码与译码功能,同时支持文件的读写操作。 哈弗曼树,又称为最优...
哈弗曼树(Huffman Tree),也称为最优二叉树,是数据结构中的一种特殊二叉树,主要用于数据的编码和解码,特别是在文本压缩中起到关键作用。它通过一种贪心策略构建,使得带权路径长度最短,从而达到编码效率最高。...
用C语言实现的哈弗曼树的解码以及编码,读入文件编码后保存为另外一个文件。
哈弗曼树的构建过程基于哈夫曼编码,它是一种前缀编码,即任何字符的编码都不会是其他字符编码的前缀,这确保了编码的唯一性。 在哈夫曼树的构建过程中,首先需要统计信源中各符号(通常为字符)出现的概率。这些...
解码过程中,通常需要维护一个哈弗曼树结构,以便根据输入的M进制编码找到对应的字符。如果哈弗曼树的构建或遍历方式不够优化,可能会导致解码速度较慢。 为了改善解码效率,可以从以下几个方面着手: 1. **优化...
哈弗曼编码是一种高效的数据压缩方法,它利用了字符出现频率的不同来构建最优的二叉树,也称为哈弗曼树。在这个C++程序中,我们将会深入理解哈弗曼编码的原理及其在实际编码过程中的应用。 首先,我们要知道哈弗曼...
给定一个哈弗曼编码,我们需要根据哈弗曼树来解码。从根节点出发,按照编码中的“0”和“1”沿着树的分支移动,当到达叶子节点时,就找到了对应的字符或数据元素。这个过程需要哈弗曼树结构作为参考。 4. **显示码...
哈弗曼树,又称霍夫曼树,是一种特殊的二叉树,主要用于数据的高效编码,尤其是在数据压缩领域有着广泛的应用。这种树结构的特点是:树中任一节点的两个子节点都是子树中权值最小的两个节点。权值在这里通常代表字符...